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

import com.alibaba.fastjson.JSON;
import com.google.common.collect.Lists;
import com.google.common.util.concurrent.ThreadFactoryBuilder;

import com.pcloud.appcenter.app.dto.AppDto;
import com.pcloud.book.base.exception.BookBizException;
import com.pcloud.book.clock.dto.PushBookClockKeywordDTO;
import com.pcloud.book.consumer.app.AppConsr;
import com.pcloud.book.consumer.channel.QrcodeSceneConsr;
import com.pcloud.book.consumer.reader.ReaderConsr;
import com.pcloud.book.consumer.user.AdviserConsr;
import com.pcloud.book.consumer.wechatgroup.WechatGroupConsr;
import com.pcloud.book.group.biz.BookGroupClassifyBiz;
import com.pcloud.book.group.dao.BookGroupClassifyDao;
import com.pcloud.book.group.dto.GroupClassifyQrcodeDTO;
import com.pcloud.book.group.vo.BookGroupClassifyVO;
import com.pcloud.book.group.vo.ListGroupClassifyParam;
import com.pcloud.book.util.common.YesOrNoEnums;
import com.pcloud.book.weixinclock.biz.WeixinClockBiz;
import com.pcloud.book.weixinclock.biz.WeixinClockPraiseBiz;
import com.pcloud.book.weixinclock.check.WeixinClockCheck;
import com.pcloud.book.weixinclock.dao.WeixinClockBrowseDao;
import com.pcloud.book.weixinclock.dao.WeixinClockCouponDao;
import com.pcloud.book.weixinclock.dao.WeixinClockDao;
import com.pcloud.book.weixinclock.dao.WeixinClockGroupClassifyDao;
import com.pcloud.book.weixinclock.dao.WeixinClockMemberDao;
import com.pcloud.book.weixinclock.dao.WeixinClockPraiseDao;
import com.pcloud.book.weixinclock.dao.WeixinClockPrizeRecordDao;
import com.pcloud.book.weixinclock.dao.WeixinClockRewardDao;
import com.pcloud.book.weixinclock.dao.WeixinClockTopicDao;
import com.pcloud.book.weixinclock.dao.WeixinClockUserCouponDao;
import com.pcloud.book.weixinclock.dto.DrawRewardDto;
import com.pcloud.book.weixinclock.dto.ListWeixinClockRankDto;
import com.pcloud.book.weixinclock.dto.RankDto;
import com.pcloud.book.weixinclock.dto.WeixinClockDto;
import com.pcloud.book.weixinclock.entity.WeixinClock;
import com.pcloud.book.weixinclock.entity.WeixinClockBrowse;
import com.pcloud.book.weixinclock.entity.WeixinClockCoupon;
import com.pcloud.book.weixinclock.entity.WeixinClockGroupClassify;
import com.pcloud.book.weixinclock.entity.WeixinClockMember;
import com.pcloud.book.weixinclock.entity.WeixinClockPraise;
import com.pcloud.book.weixinclock.entity.WeixinClockPrizeRecord;
import com.pcloud.book.weixinclock.entity.WeixinClockTopic;
import com.pcloud.book.weixinclock.entity.WeixinClockUserCoupon;
import com.pcloud.book.weixinclock.vo.request.CouponRequestVO;
import com.pcloud.book.weixinclock.vo.response.GetClockCouponResponseVO;
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.core.constant.MQTopicProducer;
import com.pcloud.common.core.constant.ProductTypeConstant;
import com.pcloud.common.core.constant.WXKeywordOperationConstant;
import com.pcloud.common.core.dto.PromotionGiftDto;
import com.pcloud.common.core.dto.PromotionOrderDto;
import com.pcloud.common.core.enums.PromotionOrderEnum;
import com.pcloud.common.enums.AppTypeEnum;
import com.pcloud.common.exceptions.BizException;
import com.pcloud.common.page.PageBeanNew;
import com.pcloud.common.page.PageParam;
import com.pcloud.common.utils.DateNewUtils;
import com.pcloud.common.utils.ListUtils;
import com.pcloud.common.utils.ResponseHandleUtil;
import com.pcloud.common.utils.cache.redis.JedisClusterUtils;
import com.pcloud.common.utils.httpclient.UrlUtils;
import com.pcloud.common.utils.string.StringUtil;
import com.pcloud.labelcenter.label.service.LabelService;
import com.pcloud.readercenter.wechat.entity.WechatGroupUser;
import com.pcloud.wechatgroup.group.dto.GroupUserDTO;
import com.sdk.wxgroup.SendTextMessageVO;
import com.sdk.wxgroup.WxGroupSDK;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.amqp.core.AmqpTemplate;
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.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
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;

/**
 * @author 杨涛
 * @description TODO
 * @date 2019/8/14 19:12
 */
@Component("weixinClockBiz")
public class WeixinClockBizImpl implements WeixinClockBiz {

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

    @Autowired
    private WeixinClockDao weixinClockDao;
    @Autowired
    private BookGroupClassifyDao bookGroupClassifyDao;
    @Autowired
    private WechatGroupConsr wechatGroupConsr;
    @Autowired
    private LabelService labelService;
    @Autowired
    private WeixinClockRewardDao weixinClockRewardDao;
    @Autowired
    private WeixinClockGroupClassifyDao weixinClockGroupClassifyDao;
    @Autowired
    private AppConsr appConsr;
    @Autowired
    private WeixinClockMemberDao weixinClockMemberDao;
    @Autowired
    private WeixinClockTopicDao weixinClockTopicDao;
    @Autowired
    private BookGroupClassifyBiz bookGroupClassifyBiz;
    @Autowired
    private QrcodeSceneConsr qrcodeSceneConsr;
    @Autowired
    private AmqpTemplate amqpTemplate;
    @Autowired
    private ReaderConsr readerConsr;
    @Autowired
    private WeixinClockCheck weixinClockCheck;
    @Autowired
    private WeixinClockPrizeRecordDao weixinClockPrizeRecordDao;
    @Autowired
    private AdviserConsr adviserConsr;
    @Autowired
    private WeixinClockPraiseBiz weixinClockPraiseBiz;
    @Autowired
    private WeixinClockBrowseDao weixinClockBrowseDao;
    @Autowired
    private WeixinClockPraiseDao weixinClockPraiseDao;
    @Autowired
    private WeixinClockCouponDao weixinClockCouponDao;
    @Autowired
    private WeixinClockUserCouponDao weixinClockUserCouponDao;

    private static final ThreadFactory NAMED_THREAD_FACTORY = new ThreadFactoryBuilder()
            .setNameFormat("weixinclock-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());

    @Value("${wechat.group.link.prefix}")
    private String wechatGroupLinkPrefix;


    /**
     * 关创建微信群签到打卡
     * @param weixinClockDto
     */
    @Override
    @ParamLog("创建微信群签到打卡")
    @Transactional(rollbackFor = Exception.class)
    public Long createWeixinClock(WeixinClockDto weixinClockDto) throws BizException {
        if(null == weixinClockDto) {
            throw new BookBizException(BookBizException.ERROR,"缺少必要参数！");
        }
        weixinClockCheck.checkParam4CreateWeixinClock(weixinClockDto);
        WeixinClock weixinClock = new WeixinClock();
        BeanUtils.copyProperties(weixinClockDto, weixinClock);
        weixinClockDao.insert(weixinClock);
        Long weixinClockId = weixinClock.getWeixinClockId();
        if(!ListUtils.isEmpty(weixinClockDto.getGroupClassifyIds())) {
            List<WeixinClockGroupClassify> groupClassifyIds = Lists.newArrayList();
            weixinClockDto.getGroupClassifyIds().forEach(e -> {
                WeixinClockGroupClassify weixinClockGroupClassify = new WeixinClockGroupClassify();
                weixinClockGroupClassify.setBookGroupClassifyId(e);
                weixinClockGroupClassify.setWeixinClockId(weixinClockId);
                groupClassifyIds.add(weixinClockGroupClassify);
            });
            weixinClockGroupClassifyDao.batchInsert(groupClassifyIds);
        }
        if(!ListUtils.isEmpty(weixinClockDto.getWeixinClockRewards())) {
            weixinClockDto.getWeixinClockRewards().forEach(e -> e.setWeixinClockId(weixinClockId));
            weixinClockRewardDao.batchInsert(weixinClockDto.getWeixinClockRewards());
        }
        if (null != weixinClockDto.getIsOpenCoupon() && weixinClockDto.getIsOpenCoupon() == 1){
            //新增打卡奖励优惠券
            CouponRequestVO vo = weixinClockDto.getCoupon();
            vo.setUserId(weixinClockDto.getCreateUser());
            WeixinClockCoupon coupon = CouponRequestVO.valueToEntity(vo);
            coupon.setWeixinClockId(weixinClockId);
            weixinClockCouponDao.insert(coupon);
        }
        return weixinClockId;
    }

    @Override
    @ParamLog("获取编辑所有的分类")
    public PageBeanNew<BookGroupClassifyVO> listGroupClassify4Clock(ListGroupClassifyParam listGroupClassifyParam, Long adviserId) throws BizException {
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("adviserId", adviserId);
        if (!StringUtil.isEmpty(listGroupClassifyParam.getName())) {
            paramMap.put("name", listGroupClassifyParam.getName());
        }
        paramMap.put("bookIds", listGroupClassifyParam.getBookIds());
        paramMap.put("proLabelId",listGroupClassifyParam.getProLabelId());
        paramMap.put("depLabelId",listGroupClassifyParam.getDepLabelId());
        paramMap.put("purLabelId",listGroupClassifyParam.getPurLabelId());
        PageParam pageParam = new PageParam(listGroupClassifyParam.getCurrentPage(), listGroupClassifyParam.getNumPerPage());
        PageBeanNew<BookGroupClassifyVO> pageBeanNew = bookGroupClassifyDao.listPageNew(pageParam, paramMap, "listGroupClassify4Clock");
        if (pageBeanNew == null) {
            return new PageBeanNew<>(listGroupClassifyParam.getCurrentPage(), listGroupClassifyParam.getNumPerPage(), new ArrayList<>());
        }
        //遍历填充标签
        List<BookGroupClassifyVO> bookGroupClassifyVOS = pageBeanNew.getRecordList();
        if (!ListUtils.isEmpty(bookGroupClassifyVOS)) {
            List<Long> labelIds = new ArrayList<>();
            List<Long> classifyIds = new ArrayList<>();
            for (BookGroupClassifyVO bookGroupClassifyVO : bookGroupClassifyVOS) {
                classifyIds.add(bookGroupClassifyVO.getClassifyId());
                if (bookGroupClassifyVO.getProLabelId() != null) {
                    labelIds.add(bookGroupClassifyVO.getProLabelId());
                }
                if (bookGroupClassifyVO.getPurLabelId() != null) {
                    labelIds.add(bookGroupClassifyVO.getPurLabelId());
                }
                if (bookGroupClassifyVO.getDepLabelId() != null) {
                    labelIds.add(bookGroupClassifyVO.getDepLabelId());
                }
            }
            Map<Long, Integer> activeCountMap = wechatGroupConsr.get7DayActiveUserCountByClassify(classifyIds);
            Map<Long, String> labelMap = new HashMap<>();
            if (!ListUtils.isEmpty(labelIds)) {
                labelMap = ResponseHandleUtil.parseMap(labelService.getLabelName(labelIds), Long.class, String.class);
            }
            for (BookGroupClassifyVO bookGroupClassifyVO : bookGroupClassifyVOS) {
                if (!MapUtils.isEmpty(labelMap)) {
                    Long proLabelId = bookGroupClassifyVO.getProLabelId();
                    Long purLabelId = bookGroupClassifyVO.getPurLabelId();
                    Long depLabelId = bookGroupClassifyVO.getDepLabelId();
                    if (proLabelId != null) {
                        bookGroupClassifyVO.setProLabelName(labelMap.get(proLabelId));
                    }
                    if (purLabelId != null) {
                        bookGroupClassifyVO.setPurLabelName(labelMap.get(purLabelId));
                    }
                    if (depLabelId != null) {
                        bookGroupClassifyVO.setDepLabelName(labelMap.get(depLabelId));
                    }
                }
                Integer count = activeCountMap.get(bookGroupClassifyVO.getClassifyId());
                if (count == null) {
                    bookGroupClassifyVO.setWeekActiveNumber(0);
                } else {
                    bookGroupClassifyVO.setWeekActiveNumber(count);
                }
            }
        }
        return pageBeanNew;
    }

    /**
     * 删除微信群签到打卡
     * @param weixinClockId
     * @param adviserId
     */
    @Override
    @ParamLog("删除微信群签到打卡")
    @Transactional(rollbackFor = Exception.class)
    public void deleteWeixinClock(Long weixinClockId, Long adviserId) throws BizException {
        if(null == weixinClockId){
            throw new BookBizException(BookBizException.ERROR,"缺少删除的必要参数");
        }
        Map<String,Object> paramMap = new HashMap<>();
        paramMap.put("weixinClockId",weixinClockId);
        //删除对应的群分类
        weixinClockGroupClassifyDao.deleteById(weixinClockId);
        //删除对应的奖励信息
        weixinClockRewardDao.deleteById(weixinClockId);
        //删除主表的微信群签到打卡
        weixinClockDao.deleteWeixinClock(paramMap);
    }

    /**
     * 修改微信群签到打卡
     * @param weixinClockDto
     * @throws BizException
     */
    @Override
    @ParamLog("修改微信群签到打卡")
    @Transactional(rollbackFor = Exception.class)
    public void updateWeixinClock(WeixinClockDto weixinClockDto) throws BizException {
        if(null == weixinClockDto) {
            throw new BookBizException(BookBizException.ERROR,"缺少必要参数！");
        }
        if(null == weixinClockDto.getWeixinClockId()){
            throw new BookBizException(BookBizException.ERROR,"缺少修改的必要参数");
        }
        weixinClockCheck.checkParam4CreateWeixinClock(weixinClockDto);
        Long weixinClockId = weixinClockDto.getWeixinClockId();
        WeixinClock weixinClock = new WeixinClock();
        BeanUtils.copyProperties(weixinClockDto, weixinClock);
        weixinClockDao.update(weixinClock);
        //删除对应的群分类
        weixinClockGroupClassifyDao.deleteById(weixinClockId);
        //删除对应的基本信息
        weixinClockRewardDao.deleteById(weixinClockId);
        if(!ListUtils.isEmpty(weixinClockDto.getGroupClassifyIds())) {
            List<WeixinClockGroupClassify> groupClassifyIds = Lists.newArrayList();
            weixinClockDto.getGroupClassifyIds().forEach(e -> {
                WeixinClockGroupClassify weixinClockGroupClassify = new WeixinClockGroupClassify();
                weixinClockGroupClassify.setBookGroupClassifyId(e);
                weixinClockGroupClassify.setWeixinClockId(weixinClockId);
                groupClassifyIds.add(weixinClockGroupClassify);
            });
            weixinClockGroupClassifyDao.batchInsert(groupClassifyIds);
        }
        if(!ListUtils.isEmpty(weixinClockDto.getWeixinClockRewards())) {
            weixinClockDto.getWeixinClockRewards().forEach(e -> e.setWeixinClockId(weixinClockId));
            weixinClockRewardDao.batchInsert(weixinClockDto.getWeixinClockRewards());
        }
        if (weixinClockDto.getIsOpenCoupon() == 1){
            CouponRequestVO vo = weixinClockDto.getCoupon();
            vo.setUserId(weixinClockDto.getCreateUser());
            WeixinClockCoupon newCoupon = CouponRequestVO.valueToEntity(vo);
            newCoupon.setWeixinClockId(weixinClockId);
            WeixinClockCoupon oldCoupon = weixinClockCouponDao.getBaseByClockId(weixinClockId);
            if (null == oldCoupon){
                //如果未设置过优惠券，则新增
                weixinClockCouponDao.insert(newCoupon);
            } else {
                //否则，修改
                newCoupon.setId(oldCoupon.getId());
                weixinClockCouponDao.update(newCoupon);
            }
        }
    }

    @Override
    public PageBeanNew<WeixinClockDto> listWeixinClock4Adviser(PageParam pageParam, Map<String, Object> paramMap) throws BizException {
        PageBeanNew<WeixinClockDto> clockDtoPage = weixinClockDao.listPageNew(pageParam, paramMap, "listWeixinClock4Adviser");
        if (clockDtoPage == null || ListUtils.isEmpty(clockDtoPage.getRecordList())) {
            return new PageBeanNew<>(pageParam.getPageNum(), pageParam.getNumPerPage(), 0, new ArrayList<>());
        }
        //开启的抽奖应用id
        List<Long> appIds = clockDtoPage.getRecordList().stream().filter(clock -> clock.getIsOpenPrize() == 1).map(WeixinClockDto::getClockPrizeId).collect(Collectors.toList());
        if(!ListUtils.isEmpty(appIds)) {
            Map<Long, AppDto> resultsMap = appConsr.getBaseByIds(appIds);
            for(WeixinClockDto weixinClockDto:clockDtoPage.getRecordList()){
                if(null != resultsMap && resultsMap.containsKey(weixinClockDto.getClockPrizeId())){
                    AppDto appDto = resultsMap.get(weixinClockDto.getClockPrizeId());
                    DrawRewardDto drawRewardDto = new DrawRewardDto();
                    drawRewardDto.setAppId(weixinClockDto.getClockPrizeId());
                    drawRewardDto.setChannelId(appDto.getChannelId());
                    drawRewardDto.setSquareImg(appDto.getSquareImg());
                    drawRewardDto.setTitle(appDto.getTitle());
                    drawRewardDto.setTypeCode(appDto.getTypeCode());
                    weixinClockDto.setDrawRewardDto(drawRewardDto);
                }
            }
        }
        //开启优惠券的打卡id
        List<Long> clockIds = clockDtoPage.getRecordList().stream().filter(clock -> clock.getIsOpenCoupon() == 1).map(WeixinClockDto::getWeixinClockId).collect(Collectors.toList());
        if (ListUtils.isEmpty(clockIds)){
            return clockDtoPage;
        }
        Map<Long, WeixinClockCoupon> couponMap = weixinClockCouponDao.getByClockIds(clockIds);
        if (MapUtils.isEmpty(couponMap)){
            return clockDtoPage;
        }
        for (WeixinClockDto weixinClockDto : clockDtoPage.getRecordList()){
            WeixinClockCoupon coupon = couponMap.get(weixinClockDto.getWeixinClockId());
            if (null == couponMap.get(weixinClockDto.getWeixinClockId())){
                continue;
            }
            weixinClockDto.setCoupon(CouponRequestVO.valueOfEntity(coupon));
        }
        return clockDtoPage;
    }

    @Override
    public WeixinClockDto getWeixinClockBaseInfo(Long weixinClockId) throws BizException {
        WeixinClockDto weixinClockDto = weixinClockDao.getWeixinClockBaseInfo(weixinClockId);
        if(null == weixinClockDto){
            return new WeixinClockDto();
        }
        if(null != weixinClockDto.getClockPrizeId() && !weixinClockDto.getClockPrizeId().equals(0L)) {
            AppDto appDto = appConsr.getBaseById(weixinClockDto.getClockPrizeId());
            appDto = null == appDto ? new AppDto() :appDto;
            DrawRewardDto drawRewardDto = new DrawRewardDto();
            drawRewardDto.setAppId(weixinClockDto.getClockPrizeId());
            drawRewardDto.setChannelId(appDto.getChannelId());
            drawRewardDto.setSquareImg(appDto.getSquareImg());
            drawRewardDto.setTitle(appDto.getTitle());
            drawRewardDto.setTypeCode(appDto.getTypeCode());
            weixinClockDto.setDrawRewardDto(drawRewardDto);
        }
        if (null != weixinClockDto.getIsOpenCoupon() && weixinClockDto.getIsOpenCoupon() == 1){
            //如果开启了打卡优惠券
            WeixinClockCoupon weixinClockCoupon = weixinClockCouponDao.getBaseByClockId(weixinClockId);
            CouponRequestVO vo = CouponRequestVO.valueOfEntity(weixinClockCoupon);
            weixinClockDto.setCoupon(vo);
        }
        return weixinClockDto;
    }

    @Override
    @ParamLog("获取某个微信群签到打卡的所有群分类详情")
    public PageBeanNew<BookGroupClassifyVO> listGroupClassifyDetail4Clock(Long weixinClockId, Integer currentPage, Integer numPerPage) throws BizException {
        if(null == weixinClockId) {
            throw new BookBizException(BookBizException.ERROR,"缺少微信打卡标识的必要参数！");
        }
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("weixinClockId", weixinClockId);
        PageParam pageParam = new PageParam(currentPage, numPerPage);
        PageBeanNew<BookGroupClassifyVO> pageBeanNew = weixinClockDao.listPageNew(pageParam, paramMap, "listGroupClassifyDetail4Clock");
        if (pageBeanNew == null) {
            return new PageBeanNew<>(currentPage, numPerPage, 0, new ArrayList<>());
        }
        List<BookGroupClassifyVO> bookGroupClassifyVOS = pageBeanNew.getRecordList();
        if (!ListUtils.isEmpty(bookGroupClassifyVOS)) {
            List<Long> classifyIds = bookGroupClassifyVOS.stream().map(BookGroupClassifyVO::getClassifyId).collect(Collectors.toList());
            Map<Long, Integer> activeCountMap = wechatGroupConsr.get7DayActiveUserCountByClassify(classifyIds);
            for (BookGroupClassifyVO bookGroupClassifyVO : bookGroupClassifyVOS) {
                //最近7天活跃人数
                Integer count = activeCountMap.get(bookGroupClassifyVO.getClassifyId());
                if (count == null) {
                    bookGroupClassifyVO.setWeekActiveNumber(0);
                } else {
                    bookGroupClassifyVO.setWeekActiveNumber(count);
                }
            }
        }
        return pageBeanNew == null ? new PageBeanNew() : pageBeanNew;
    }

    @Override
    @ParamLog("校验是否为该群的打卡关键字")
    public Boolean checkWeixinClockKeyword(String content, String weixinGroupId) throws BizException {
        LOGGER.info("content----->"+content+"weixinGroupId----->"+weixinGroupId);
        //简单过滤非关键词的词
        if (StringUtil.isEmpty(content) || content.length() > 10) {
            return false;
        }
        //通过群id获取对应基本信息
        GroupClassifyQrcodeDTO classifyQrcodeInfo = bookGroupClassifyBiz.getClassifyQrcodeInfo(weixinGroupId);
        if(null == classifyQrcodeInfo){
            return false;
        }
        Map<String,Object> paramMap = new HashMap<>();
        paramMap.put("bookGroupClassifyId",classifyQrcodeInfo.getClassifyId());
        String aimKeyword = weixinClockGroupClassifyDao.getKeywordByGroupClassify(paramMap);
        LOGGER.info("aimKeyword=" + aimKeyword + "content=" + content);
        return content.equalsIgnoreCase(aimKeyword);
    }

    private String getClockRankUrl(Long adviserId, Long clockPrizeId, String wxGroupId, String wxUserId){
        StringBuffer sbu=new StringBuffer();
        if(null != clockPrizeId  && !clockPrizeId.equals(0L)) {
            AppDto appDto = appConsr.getBaseById(clockPrizeId);
            AccountSettingDto accountSettingDto = qrcodeSceneConsr.getWechatInfo(appDto.getChannelId());
            if (null == accountSettingDto) {
                return "";
            }
            String protocol = accountSettingDto.getProtocol();
            if (StringUtils.isEmpty(protocol)) {
                protocol = ChannelConstants.HTTP;
            }
            sbu.append(protocol).append(accountSettingDto.getDomain()).append("/W")
                    .append(accountSettingDto.getAccountSettingId()).append("/clock").append("?wxGroupId=")
                    .append(wxGroupId).append("&wxUserId=").append(wxUserId);
            return UrlUtils.getShortUrl4Own(sbu.toString());
        }
        if(null != adviserId && !adviserId.equals(0L)){
            Long channelId = adviserConsr.getDefaultChannel(adviserId);
            AccountSettingDto accountSettingDto = qrcodeSceneConsr.getWechatInfo(channelId);
            if (null == accountSettingDto) {
                return "";
            }
            String protocol = accountSettingDto.getProtocol();
            if (StringUtils.isEmpty(protocol)) {
                protocol = ChannelConstants.HTTP;
            }
            sbu.append(protocol).append(accountSettingDto.getDomain()).append("/W")
                    .append(accountSettingDto.getAccountSettingId()).append("/clock").append("?wxGroupId=")
                    .append(wxGroupId).append("&wxUserId=").append(wxUserId);
            return UrlUtils.getShortUrl4Own(sbu.toString());
        }
        return "";
    }

    private String getClockRewardUrl(Long clockPrizeId){
        StringBuffer sbu=new StringBuffer();
        if(null != clockPrizeId  && !clockPrizeId.equals(0L)) {
            AppDto appDto = appConsr.getBaseById(clockPrizeId);
            AccountSettingDto accountSettingDto = qrcodeSceneConsr.getWechatInfo(appDto.getChannelId());
            if(null == accountSettingDto){
                return "";
            }
            String protocol = accountSettingDto.getProtocol();
            if (StringUtils.isEmpty(protocol)) {
                protocol = ChannelConstants.HTTP;
            }
            Long random = accountSettingDto.getRandom();
            if (null == random) {
                random = accountSettingDto.getAccountSettingId();
            }
            sbu.append(protocol).append("weixin").append(random).append(".").append(accountSettingDto.getFirstDomain())
                    .append("/luck").append("/W").append(accountSettingDto.getAccountSettingId()).append("/C").append(appDto.getChannelId())
                    .append("/A").append(appDto.getAppId())
                    .append("/luckPage?isPreview=1&adviserId=").append(appDto.getCreatedUser()).append("&appType==").append(appDto.getTypeCode())
                    .append("&origin=wxGroup");

            LOGGER.info("抽奖的跳转链接=====" + sbu.toString() + "================s");
            return UrlUtils.getShortUrl4Own(sbu.toString());
        }
        return "";
    }

    private String getCouponUrl(Long adviserId, Long clockPrizeId, String wxGroupId, String wxUserId){
        StringBuffer sbu=new StringBuffer();
        if(null != clockPrizeId  && !clockPrizeId.equals(0L)) {
            AppDto appDto = appConsr.getBaseById(clockPrizeId);
            AccountSettingDto accountSettingDto = qrcodeSceneConsr.getWechatInfo(appDto.getChannelId());
            if (null == accountSettingDto) {
                return "";
            }
            String protocol = accountSettingDto.getProtocol();
            if (StringUtils.isEmpty(protocol)) {
                protocol = ChannelConstants.HTTP;
            }
            sbu.append(protocol).append(accountSettingDto.getDomain()).append("/W")
                    .append(accountSettingDto.getAccountSettingId()).append("/clockcoupon").append("?wxGroupId=")
                    .append(wxGroupId);
            return UrlUtils.getShortUrl4Own(sbu.toString());
        }
        if(null != adviserId && !adviserId.equals(0L)){
            Long channelId = adviserConsr.getDefaultChannel(adviserId);
            AccountSettingDto accountSettingDto = qrcodeSceneConsr.getWechatInfo(channelId);
            if (null == accountSettingDto) {
                return "";
            }
            String protocol = accountSettingDto.getProtocol();
            if (StringUtils.isEmpty(protocol)) {
                protocol = ChannelConstants.HTTP;
            }
            sbu.append(protocol).append(accountSettingDto.getDomain()).append("/W")
                    .append(accountSettingDto.getAccountSettingId()).append("/clockcoupon").append("?wxGroupId=")
                    .append(wxGroupId);
            return UrlUtils.getShortUrl4Own(sbu.toString());
        }
        return "";
    }

    /**
     * 发送关键词信息
     * @param content
     * @param userWxId
     * @return
     */
    @Override
    @ParamLog("为微信群打卡关键词，发送关键词信息")
    @Transactional(rollbackFor = Exception.class)
    public Boolean sendKeywordMessage(String content, String userWxId,String wechatGroupId, String wxId, String ip) {
        LOGGER.info("接受到的关键词信息" + content);
        GroupClassifyQrcodeDTO classifyQrcodeInfo = bookGroupClassifyBiz.getClassifyQrcodeInfo(wechatGroupId);
        if(null == classifyQrcodeInfo){
            return false;
        }
        WeixinClockDto weixinClockDto = weixinClockGroupClassifyDao.getClockBaseInfoByClassify(classifyQrcodeInfo.getClassifyId());
        WeixinClockMember clockMember = weixinClockMemberDao.getByWxUserId(wechatGroupId, userWxId);
        AppDto appDto = appConsr.getBaseById(weixinClockDto.getClockPrizeId());
        Long channelId = classifyQrcodeInfo.getChannelId();
        if (null == channelId) {
            if (null == appDto) {
                channelId = adviserConsr.getDefaultChannel(weixinClockDto.getCreateUser());
            } else {
                channelId = appDto.getChannelId();
            }
        }
        Long wechatUserId = readerConsr.getWechatUserId(userWxId, channelId);
        GroupUserDTO groupUserDTO = wechatGroupConsr.getWxUserInfoByWxUserId(userWxId);
        groupUserDTO = null == groupUserDTO ? new GroupUserDTO() : groupUserDTO;
        Long weixinClockMemberId = clockMember == null ? null : clockMember.getWeixinClockMemberId();
        if(null == clockMember) {
            WeixinClockMember weixinClockMember = new WeixinClockMember();
            weixinClockMember.setWeixinClockId(weixinClockDto.getWeixinClockId());
            weixinClockMember.setAllClockDay(0);
            weixinClockMember.setBookGroupClassifyId(classifyQrcodeInfo.getClassifyId());
            weixinClockMember.setHeadPic(groupUserDTO.getHeadPic());
            weixinClockMember.setNickname(groupUserDTO.getNickName());
            weixinClockMember.setWxGroupId(wechatGroupId);
            weixinClockMember.setWxUserId(userWxId);
            weixinClockMember.setWechatUserId(wechatUserId);
            weixinClockMember.setScore(0);
            weixinClockMemberDao.insert(weixinClockMember);
            weixinClockMemberId = weixinClockMember.getWeixinClockMemberId();
        }
        SendTextMessageVO vo = new SendTextMessageVO();
        vo.setAltId(wxId);
        vo.setWxGroupId(wechatGroupId);
        vo.setIp(ip);
        String sendContent = "";
        String nickname = groupUserDTO.getNickName();
        if(StringUtil.isEmpty(nickname)){
            nickname = "神秘客";
        }
        WeixinClockTopic weixinTopic = weixinClockTopicDao.getTopicByIds4Today(wechatGroupId, userWxId);
        //获取我获得的点赞数
        Integer praiseNum = weixinClockPraiseDao.getPraiseNum(wechatGroupId, userWxId);
        if(null == weixinTopic){
            WeixinClockTopic weixinClockTopic = new WeixinClockTopic();
            weixinClockTopic.setBookGroupClassifyId(classifyQrcodeInfo.getClassifyId());
            weixinClockTopic.setCreatedDay(new Date());
            weixinClockTopic.setWeixinClockId(weixinClockDto.getWeixinClockId());
            weixinClockTopic.setWxGroupId(wechatGroupId);
            weixinClockTopic.setWxUserId(userWxId);
            weixinClockTopic.setWeixinClockMemberId(weixinClockMemberId);
            //修改打卡天数， 天数+1， 得分+1
            weixinClockMemberDao.updateClockDays(wechatGroupId, userWxId, wechatUserId);
            weixinClockTopicDao.insert(weixinClockTopic);
            //发topic，增加抽奖次数
            //发送抽奖的TOPIC
            Long clockDays = weixinClockTopicDao.getClockCountByUser(wechatGroupId, userWxId);
            if(null != weixinClockDto.getClockPrizeId()) {
                if (null != wechatUserId && !wechatUserId.equals(0L)) {
                    EXECUTOR_SERVICE.execute(() -> {
                        LOGGER.info("异步校验是否满足抽奖要求,clockDays=" + clockDays);
                        PromotionOrderDto promotionOrderDto = new PromotionOrderDto();
                        List<PromotionGiftDto> promotionGiftDtoList = new ArrayList<>();
                        PromotionGiftDto promotionGiftDto = new PromotionGiftDto();
                        promotionGiftDto.setTargetClass(PromotionOrderEnum.TARGET_CLASS_APP.getCode());
                        promotionGiftDto.setTargetType(AppTypeEnum.DRAW.value);
                        promotionGiftDto.setTargetId(weixinClockDto.getClockPrizeId());
                        Integer grantNum = weixinClockRewardDao.getGrantNumFromReward(weixinClockDto.getWeixinClockId(), clockDays);
                        promotionGiftDto.setGrantNum(grantNum == null ? "0" : grantNum.toString());
                        promotionGiftDtoList.add(promotionGiftDto);
                        promotionOrderDto.setGifts(promotionGiftDtoList);
                        promotionOrderDto.setUserId(wechatUserId);
                        LOGGER.info("发送抽奖规则,参数：promotionOrderDto=" + promotionOrderDto);
                        amqpTemplate.convertAndSend(MQTopicProducer.EXCHAGE, MQTopicProducer.GIVE_GIFT, promotionOrderDto);
                    });
                } else {
                    WeixinClockPrizeRecord weixinClockPrizeRecord1 = weixinClockPrizeRecordDao.selectByWxUserIdAndAppId(userWxId, weixinClockDto.getClockPrizeId());
                    LOGGER.info("weixinClockPrizeRecord1=====" + weixinClockPrizeRecord1);
                    if (null == weixinClockPrizeRecord1) {
                        WeixinClockPrizeRecord weixinClockPrizeRecord2 = new WeixinClockPrizeRecord();
                        weixinClockPrizeRecord2.setClockPrizeId(weixinClockDto.getClockPrizeId());
                        weixinClockPrizeRecord2.setWxUserId(userWxId);
                        Integer grantNum = weixinClockRewardDao.getGrantNumFromReward(weixinClockDto.getWeixinClockId(), clockDays);
                        weixinClockPrizeRecord2.setPrizeTime(grantNum == null ? 0 : grantNum);
                        LOGGER.info("weixinClockPrizeRecord2------" + weixinClockPrizeRecord2);
                        weixinClockPrizeRecordDao.insert(weixinClockPrizeRecord2);
                    } else {
                        Integer grantNum = weixinClockRewardDao.getGrantNumFromReward(weixinClockDto.getWeixinClockId(), clockDays);
                        grantNum = grantNum == null ? 0 : grantNum;
                        weixinClockPrizeRecordDao.updatePrizeTime(userWxId, weixinClockDto.getClockPrizeId(), grantNum);
                    }
                }
            }
            //获取我的新排名
            Integer newOrder = weixinClockMemberDao.getMyNewOrder(wechatGroupId, userWxId);
            String clockRewardUrl = getClockRewardUrl(weixinClockDto.getClockPrizeId());
            String clockRankUrl = getClockRankUrl(weixinClockDto.getCreateUser(), weixinClockDto.getClockPrizeId(), wechatGroupId, userWxId);
            Calendar today = Calendar.getInstance();
            int month = today.get(Calendar.MONTH) + 1;
            int dayOfMonth = today.get(Calendar.DAY_OF_MONTH);
            Integer grantNum = weixinClockRewardDao.getGrantNumFromReward(weixinClockDto.getWeixinClockId(), clockDays);
            if(null == weixinClockDto.getClockPrizeId()){
                grantNum = 0;
            }
            sendContent = "@" + nickname + "   "+ weixinClockDto.getClockIntroduction() + "\n" + month + "月" + dayOfMonth + "日打卡成功，你已累积打卡"
                    + clockDays + "天，累计收获" + praiseNum + "个赞，排名第" +
                    newOrder + "，明天继续！" + "\n" + "\n" + "点赞与排行榜：" + "\n" + "-->" + clockRankUrl + "\n";
            if (null != weixinClockDto.getIsOpenCoupon() && YesOrNoEnums.YES.getValue().equals(weixinClockDto.getIsOpenCoupon())){
                //如果有设置奖励优惠券
                WeixinClockCoupon weixinClockCoupon = weixinClockCouponDao.getBaseByClockId(weixinClockDto.getWeixinClockId());
                if (weixinClockCoupon.getDayNum() == clockDays.intValue()){
                    WeixinClockUserCoupon weixinClockUserCoupon = new WeixinClockUserCoupon();
                    weixinClockUserCoupon.setWxGroupId(wechatGroupId);
                    weixinClockUserCoupon.setWxUserId(userWxId);
                    weixinClockUserCoupon.setWeixinClockId(weixinClockDto.getWeixinClockId());
                    weixinClockUserCoupon.setClockCouponId(weixinClockCoupon.getId());
                    weixinClockUserCoupon.setWechatUserId(wechatUserId);
                    weixinClockUserCouponDao.insert(weixinClockUserCoupon);
                    String couponUrl = getCouponUrl(weixinClockDto.getCreateUser(), weixinClockDto.getClockPrizeId(), wechatGroupId, userWxId);
                    sendContent += "打卡奖励：" + weixinClockCoupon.getCouponPrice() + "元优惠券\n-->" + couponUrl + "\n";
                }
            }
            if(null != grantNum && !grantNum.equals(0)){
                sendContent +=  "点击抽奖，即可有机会获得精美礼品哦：" + "\n" + "-->" + clockRewardUrl;
            }

        } else {
            //获取我打卡天数
            Long clockDays = weixinClockTopicDao.getClockCountByUser(wechatGroupId, userWxId);
            //获取我的排名
            Integer newOrder = weixinClockMemberDao.getMyNewOrder(wechatGroupId, userWxId);
            sendContent = "@" + nickname + " ，你今天已经打过卡了, 目前累计打卡" + clockDays + "天，累计收获" + praiseNum + "个赞，排名第" +
                    newOrder + "，明天再继续！";
        }
        vo.setContent(sendContent);
        LOGGER.info("微信群内加入并打卡：发送微信消息vo="+vo);
        // TODO sdk.message
                wechatGroupConsr.sendMessage(JSON.toJSONString(vo));
        return true;
    }

    /**
     * 获取某个群内的打卡排行榜
     * @param dto
     * @return
     */
    @Override
    @ParamLog("获取某个群内的打卡排行榜")
    public PageBeanNew<RankDto> listWeixinClockRank(ListWeixinClockRankDto dto) {
        PageParam pageParam = new PageParam(dto.getCurrentPage(), dto.getNumPerPage());
        Map<String, Object> map = new HashMap<>();
        map.put("wxGroupId", dto.getWxGroupId());
        map.put("wxUserId", dto.getWxUserId());
        PageBeanNew<RankDto> rankDtos = weixinClockMemberDao.listPageNew(pageParam, map, "listWeixinClockRank");
        if (null == rankDtos || ListUtils.isEmpty(rankDtos.getRecordList())) {
            return new PageBeanNew<>(dto.getCurrentPage(), dto.getNumPerPage(), 0, new ArrayList<>());
        }
        List<RankDto> list = rankDtos.getRecordList();
        weixinClockPraiseBiz.fillPraise(list, dto);
        rankDtos.setRecordList(list);
        //埋点，用户浏览排行榜记录
        WeixinClockBrowse clockBrowse = new WeixinClockBrowse();
        BeanUtils.copyProperties(dto, clockBrowse);
        clockBrowse.setBrowseTime(new Date());
        clockBrowse.setIpAddress(dto.getIpAddress());
        weixinClockBrowseDao.insert(clockBrowse);
        return rankDtos;
    }

    /**
     * 获取某个群内某个用户的信息
     * @param wxGroupId
     * @param wxUserId
     * @return
     */
    @Override
    @ParamLog("获取某个群内某个用户的信息")
    public RankDto getClockWechatUserRank(Long wechatUserId, String wxGroupId, String wxUserId) {
        RankDto rankDto = weixinClockMemberDao.getClockWechatUserRank(wechatUserId, wxGroupId);
        if (null == rankDto || null == rankDto.getWxUserId()){
            return new RankDto();
        }
        Integer praiseNum = weixinClockPraiseDao.getPraiseNum(wxGroupId, rankDto.getWxUserId());
        rankDto.setPraiseNum(praiseNum);
        return rankDto;
    }

    /**
     * 接收到微信用户绑定TOPIC
     * @param wechatGroupUser
     */
    @Override
    @ParamLog("微信用户绑定")
    public void receiveWxGroupUserBindTopic(WechatGroupUser wechatGroupUser) {
            List<WeixinClockPrizeRecord> weixinClockPrizeRecords = weixinClockPrizeRecordDao.getAllPrizeList(wechatGroupUser.getWxUserId());
            PromotionOrderDto promotionOrderDto = new PromotionOrderDto();
            List<PromotionGiftDto> promotionGiftDtoList = new ArrayList<>();
            for(WeixinClockPrizeRecord weixinClockPrizeRecord : weixinClockPrizeRecords){
                PromotionGiftDto promotionGiftDto = new PromotionGiftDto();
                promotionGiftDto.setTargetClass(PromotionOrderEnum.TARGET_CLASS_APP.getCode());
                promotionGiftDto.setTargetType(AppTypeEnum.DRAW.value);
                promotionGiftDto.setTargetId(weixinClockPrizeRecord.getClockPrizeId());
                Integer grantNum = weixinClockPrizeRecord.getPrizeTime();
                promotionGiftDto.setGrantNum(grantNum == null ? "0" : grantNum.toString());
                promotionGiftDtoList.add(promotionGiftDto);
            }
            promotionOrderDto.setGifts(promotionGiftDtoList);
            promotionOrderDto.setUserId(wechatGroupUser.getWechatUserId());
            LOGGER.info("发送抽奖规则,参数：promotionOrderDto=" + promotionOrderDto);
            amqpTemplate.convertAndSend(MQTopicProducer.EXCHAGE, MQTopicProducer.GIVE_GIFT, promotionOrderDto);
            weixinClockPrizeRecordDao.deleteByWxUserId(wechatGroupUser.getWxUserId());
            weixinClockMemberDao.updatMemberWechatUserId(wechatGroupUser.getWxUserId(), wechatGroupUser.getWechatUserId());
            weixinClockUserCouponDao.updateWechatUserId(wechatGroupUser.getWxUserId(), wechatGroupUser.getWechatUserId());
    }

    @Override
    public RankDto getShareMemberRank(String wxGroupId, String wxUserId) {
        RankDto rankDto = weixinClockMemberDao.getClockWechatUserRankByWxUserId(wxUserId, wxGroupId);
        if(null == rankDto){
            return new RankDto();
        }
        Integer praiseNum = weixinClockPraiseDao.getPraiseNum(wxGroupId, wxUserId);
        rankDto.setPraiseNum(praiseNum);
        return rankDto;
    }

    @Override
    public void solveOldData() {
        weixinClockMemberDao.initScore();
        List<RankDto> rankDtos = weixinClockPraiseDao.listAll();
        if (!ListUtils.isEmpty(rankDtos)) {
            for (RankDto rankDto : rankDtos) {
                weixinClockMemberDao.addPraiseNum(rankDto.getWxUserId(), rankDto.getWxGroupId(), rankDto.getPraiseNum());
            }
        }
    }

    @Override
    @ParamLog(value = "获取群打卡奖励优惠券", isAfterReturn = false)
    public GetClockCouponResponseVO getClockCoupon(String wxGroupId, Long wechatUserId) {
        if(null == wxGroupId){
            return new GetClockCouponResponseVO();
        }
        WeixinClockDto weixinClock = weixinClockDao.getByWxGroupId(wxGroupId);
        if (null == weixinClock){
            throw new BookBizException(BookBizException.ERROR, "该打卡不存在");
        }
        WeixinClockUserCoupon weixinClockUserCoupon = weixinClockUserCouponDao.getByGroupAndUser(wxGroupId, wechatUserId);
        if (null == weixinClockUserCoupon){
            WeixinClockCoupon weixinClockCoupon = weixinClockCouponDao.getBaseByClockId(weixinClock.getWeixinClockId());
            GetClockCouponResponseVO vo = new GetClockCouponResponseVO();
            if (null == weixinClockCoupon){
                vo.setHasCoupon(0);
                return vo;
            }
            vo.setHasCoupon(1);
            vo.setHasGot(0);
            vo.setDayNum(weixinClockCoupon.getDayNum());
            return vo;
        }
        WeixinClockCoupon coupon = weixinClockCouponDao.getBaseById(weixinClockUserCoupon.getClockCouponId());
        GetClockCouponResponseVO vo = GetClockCouponResponseVO.valueFromEntity(coupon);
        vo.setHasCoupon(1);
        vo.setHasGot(1);
        vo.setGetTime(weixinClockUserCoupon.getCreateTime());
        return vo;
    }

    @Override
    public void solveUserCoupon(){
        List<WeixinClockUserCoupon> userCoupons = weixinClockUserCouponDao.getNoWechatUserId();
        if (ListUtils.isEmpty(userCoupons)){
            return;
        }
        for (WeixinClockUserCoupon userCoupon : userCoupons){
            if (null == userCoupon || null == userCoupon.getWxUserId() || null == userCoupon.getWxGroupId()){
                continue;
            }
            WeixinClockMember clockMember = weixinClockMemberDao.getByWxUserId(userCoupon.getWxGroupId(), userCoupon.getWxUserId());
            if (null == clockMember || null == clockMember.getWechatUserId()){
                continue;
            }
            weixinClockUserCouponDao.updateWechatUserId(userCoupon.getWxUserId(), clockMember.getWechatUserId());
        }
    }

}
