/**
 * Project Name:tuia-youtui-web<br>
 * File Name:ActivityBOImpl.java<br>
 * Package Name:com.duiba.tuia.youtui.web.bo.impl<br>
 * Date:2017年1月24日下午2:54:32<br>
 * Copyright (c) 2017, duiba.com.cn All Rights Reserved.<br>
 */

package com.duiba.tuia.youtui.web.bo.impl;

import cn.com.duiba.goods.center.api.remoteservice.RemoteAdvertCouponGoodsBackendService;
import cn.com.duiba.goods.center.api.remoteservice.dto.AdvertCouponGoodsDto;
import cn.com.duiba.tuia.activity.center.api.common.PageDto;
import cn.com.duiba.tuia.activity.center.api.constant.*;
import cn.com.duiba.tuia.activity.center.api.dto.*;
import cn.com.duiba.tuia.activity.center.api.dto.req.*;
import cn.com.duiba.tuia.activity.center.api.remoteservice.RemoteActivityOrderService;
import cn.com.duiba.tuia.activity.center.api.remoteservice.RemoteGuidePageService;
import cn.com.duiba.tuia.activity.center.api.util.CollectionTool;
import cn.com.duiba.tuia.activity.center.api.util.EntityUtil;
import cn.com.duiba.tuia.activity.center.api.util.MathUtil;
import cn.com.duiba.tuia.ssp.center.api.dto.MediaAppDto;
import cn.com.duiba.tuia.ssp.center.api.dto.PlugBuoyConfigDto;
import cn.com.duiba.tuia.ssp.center.api.dto.SlotDto;
import cn.com.duiba.tuia.ssp.center.api.remote.RemoteActivityCenterService;
import cn.com.duiba.tuia.ssp.center.api.remote.RemoteMediaService;
import cn.com.duiba.wolf.dubbo.DubboResult;
import cn.com.duiba.wolf.utils.BeanUtils;
import cn.com.duiba.wolf.utils.DateUtils;
import cn.com.duiba.wolf.utils.UrlUtils;
import cn.com.duibaboot.ext.autoconfigure.accesslog.AccessLogFilter;
import cn.com.tuia.advert.model.QueryAdvertRsp;
import cn.com.tuia.advert.model.SpmlogReq;
import cn.com.tuia.advert.service.ISpmService;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.duiba.tuia.youtui.web.bo.ActivityBO;
import com.duiba.tuia.youtui.web.constant.*;
import com.duiba.tuia.youtui.web.constant.ErrorCode;
import com.duiba.tuia.youtui.web.embed.*;
import com.duiba.tuia.youtui.web.exception.ActivityException;
import com.duiba.tuia.youtui.web.exception.BusinessException;
import com.duiba.tuia.youtui.web.model.*;
import com.duiba.tuia.youtui.web.model.req.*;
import com.duiba.tuia.youtui.web.model.rsp.*;
import com.duiba.tuia.youtui.web.service.*;
import com.duiba.tuia.youtui.web.tool.*;
import com.google.common.base.Splitter;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang.StringUtils;
import org.joda.time.DateTime;
import org.joda.time.Hours;
import org.joda.time.Minutes;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;

/**
 * ClassName: ActivityBOImpl <br/>
 * Function: 活动业务编码. <br/>
 * date: 2017年1月24日 下午2:54:32 <br/>
 *
 * @author leiliang
 * @since JDK 1.6
 */
@Service
public class ActivityBOImpl extends BaseCacheService implements ActivityBO {

    private static final String YUN_DUIBA_COM_CN = "yun.duiba.com.cn";
    private static final String YUN_TUIA_CN = "yun.tuia.cn";
    private static final String YUN_TUISNAKE_COM = "yun.tuisnake.com";

    private LoadingCache<String, String> activitySkinConfigCache = CacheBuilder.newBuilder().maximumSize(50)// 最多存5个
            .refreshAfterWrite(1, TimeUnit.MINUTES)// 缓存1分钟刷新一次(load不到新数据时仍返回就数据)
            .expireAfterWrite(5, TimeUnit.MINUTES)// 缓存5分钟强制刷新一次
            .build(new CacheLoader<String, String>() {

                @Override
                public String load(String key) {
                    return replaceRandomDomain(key);
                }
            });

    private LoadingCache<OptionListReq, List<IDReq>> guidePageIDReqCache = CacheBuilder.newBuilder().maximumSize(50)// 最多存5个
            .refreshAfterWrite(1, TimeUnit.MINUTES)// 缓存1分钟刷新一次(load不到新数据时仍返回就数据)
            .expireAfterWrite(5, TimeUnit.MINUTES)// 缓存5分钟强制刷新一次
            .build(new CacheLoader<OptionListReq, List<IDReq>>() {

                @Override
                public List<IDReq> load(OptionListReq key) {
                    try {
                        return getGuidePagPageIdList(key);
                    } catch (Exception e) {
                        return Lists.newArrayList();
                    }
                }
            });

    /**
     * The activity service.
     */
    @Autowired
    private ActivityService activityService;

    /**
     * The remote activity order service.
     */
    @Autowired
    private RemoteActivityOrderService remoteActivityOrderService;

    /**
     * The activity order service.
     */
    @Autowired
    private ActivityOrderService activityOrderService;


    /**
     * The i spm service.
     */
    @Autowired
    private ISpmService iSpmService;

    /**
     * The remote advert coupon goods backend service.
     */
    @Autowired
    private RemoteAdvertCouponGoodsBackendService remoteAdvertCouponGoodsBackendService;

    /**
     * The luck bag service.
     */
    @Autowired
    private LuckBagService luckBagService;

    @Autowired
    private GuidePageService guidePageService;

    @Autowired
    private ActivityEngineService activityEngineService;

    @Autowired
    private PrizeService prizeService;

    @Autowired
    private RemoteMediaService remoteMediaService;

    @Autowired
    private SkinService skinService;

    @Value("${taw.redirect.domain}")
    private String redirectDomain;

    @Autowired
    private ContactPlateService contactPlateService;

    @Autowired
    private SlotService slotService;

    @Autowired
    private AppService appService;

    @Autowired
    private RemoteGuidePageService remoteGuidePageService;

    @Autowired
    private PublicNoticeStyleService publicNoticeStyleService;

    @Autowired
    private RemoteActivityCenterService remoteActivityCenterService;

    @Autowired
    private SystemConfigService systemConfigService;

    /** 直投页来源service */
    @Autowired
    private DirectPageSourceService directPageSourceService;


    /**
     * Gets the activity skin config.
     *
     * @param req the req
     * @return the activity skin config
     * @throws ActivityException the activity exception
     */
    @Override
    public GetSkinConfigRsp getActivitySkinConfig(ActivitySkinReq req, HttpServletRequest request) throws ActivityException, ExecutionException {

        // 获取活动皮肤配置
        Long activityId = req.getActivityId();

        String refer = request.getHeader(Constants.HTTPHEADER.REFERER);
        String login = null;
        if (StringUtils.isNotBlank(refer)) {
            Map<String,String> params = UrlUtils.uRLRequest(refer);
            login = params.get(Constants.LOGIN);
        }

        ActivitySkinDataDto activitySkinDataDto = activityService.selectActivitySkinByActivityId(activityId, login);
        String defaultConfig = activitySkinDataDto.getDataJson();

        GetSkinConfigRsp rsp = new GetSkinConfigRsp();
        if (StringUtils.isNotBlank(defaultConfig)) {
            rsp.setSkinConfig(defaultConfig);
        } else {
            // 获取皮肤模板默认配置
            String skinType = activitySkinDataDto.getSkinType();
            SkinTemplateDataDto skinTemplateDataDto = activityService.selectSkinTemplateBySkinType(skinType);
            rsp.setSkinConfig(skinTemplateDataDto.getStyleConfig());
        }

        // 新弹层逻辑
        Integer newLayerRate = activitySkinDataDto.getNewLayerRate() == null ? 0 : activitySkinDataDto.getNewLayerRate();
        // 弹层随机数(0.0000000000000000 到100.0000000000000000)之间的随机数
        double randomNumber = Math.random() * 100;
        rsp.setIsNew(newLayerRate >= randomNumber);

        //客服信息模版-规则说明
        ContactPlateDto contactPlateDto = contactPlateService.getDtoByHost(request.getHeader("host"));
        rsp.setContaction(contactPlateDto == null ? "" : contactPlateDto.getRuleInfo());

        // 图片域名切换
        rsp.replaceDomain(DomainUtil.getCurrentYunDomain(request));
        return rsp;

    }

    private void setSkinConfig(ActivitySkinDataDto activitySkinDataDto, String domain, ModelAndView model, long styleType) throws ActivityException {
        String defaultConfig = activitySkinDataDto.getDataJson();
        if (StringUtils.isBlank(defaultConfig)) {
            String skinType = activitySkinDataDto.getSkinType();
            SkinTemplateDataDto skinTemplateDataDto = activityService.selectSkinTemplateBySkinType(skinType);
            defaultConfig = skinTemplateDataDto.getStyleConfig();
            activitySkinDataDto.setDataJson(defaultConfig);

        }

        // 临时需求 大海捞金2 和 踹一踹 多域名加载素材
        if (("fishinggold_2".equals(activitySkinDataDto.getSkinType()) || "kickTree_1".equals(activitySkinDataDto.getSkinType()))
                && StyleTypeUtil.half(styleType) - 2 == 0) {
            try {
                defaultConfig = activitySkinConfigCache.get(activitySkinDataDto.getDataJson());
            } catch (Exception e) {
                logger.info("替换活动为CDN域名异常", e);
            }
        }

        if (StringUtils.isBlank(defaultConfig)) {
            defaultConfig = "[]";
        }

        model.addObject("skinConfig", DomainUtil.replaceDomain(defaultConfig, domain));


    }

    /**
     * 替换域名
     *
     * @param dataConfig
     * @return
     */
    private String replaceRandomDomain(String dataConfig) {
        List<String> cdnDomainList = getRandomCdnDomain();
        if (CollectionUtils.isEmpty(cdnDomainList)) {
            return dataConfig;
        }
        int i = 0; //皮肤图片索引
        int j = 0; //cdn列表图片索引

        dataConfig = dataConfig.replaceAll(YUN_DUIBA_COM_CN, YUN_TUISNAKE_COM);
        dataConfig = dataConfig.replaceAll(YUN_TUIA_CN, YUN_TUISNAKE_COM);

        while (dataConfig.indexOf(YUN_TUISNAKE_COM) > -1) {
            dataConfig = replaceDataConfig(YUN_TUISNAKE_COM, dataConfig, cdnDomainList, i, j);
            if (i % 2 == 0) {
                j++;
            }
            i++;
        }

        return dataConfig;
    }

    /**
     * 替换域名
     *
     * @param oldDomain
     * @param dataConfig
     * @param cdnDomainList
     * @param i
     * @return
     */
    private String replaceDataConfig(String oldDomain, String dataConfig, List<String> cdnDomainList, int i, int j) {
        if (i % 2 == 0) {
            dataConfig = dataConfig.replaceFirst(oldDomain, getYunSkinConfigDomain(cdnDomainList.get(j % cdnDomainList.size())));
        } else {
            dataConfig = dataConfig.replaceFirst(oldDomain, getYunSkinConfigDomain(cdnDomainList.get(cdnDomainList.size() - 1)));
        }
        return dataConfig;
    }


    /**
     * 得到所有素材CDN域名列表
     *
     * @return
     */
    private List<String> getRandomCdnDomain() {

        String value = systemConfigService.getSystemConfig("tuia_cdn_domain");
        return StringUtils.isEmpty(value) ? Lists.newArrayList() : Arrays.asList(value.split(","));
    }

    /**
     * 获取完整素材请求
     *
     * @param skinConfigDomain
     * @return
     */
    private static String getYunSkinConfigDomain(String skinConfigDomain) {
        return "yun." + skinConfigDomain;
    }

    /**
     * Gets the prize detail.
     *
     * @param req the req
     * @param consumer the consumer
     * @return the prize detail
     * @throws ActivityException the activity exception
     */
    @Override
    public PrizeDteailRsp getPrizeDetail(PrizeReq req, UserAccount consumer, HttpServletRequest request) throws ActivityException {

        ActivityOptionDto dto = activityService.selectActivityOption(req.getOptionId());
        if (null == dto) {
            throw new ActivityException(ErrorCode.E0000001.geteCode(), "奖项不存在");
        }
        String prizeType = dto.getPrizeType();
        PrizeDteailRsp rsp = new PrizeDteailRsp();
        if (ActivityOptionType.TYPE_COUPON.getCode().equals(prizeType)) {
            buildCouponOptionDetail(dto.getGid(), rsp);
        } else if (ActivityOptionType.TYPE_PHYSICAL.getCode().equals(prizeType) || ActivityOptionType.TYPE_NOTHING.getCode().equals(prizeType)) {
            buildNothingOptionDetail(dto, rsp);
        }

        rsp.replaceDomain(DomainUtil.getCurrentYunDomain(request));
        return rsp;
    }

    /**
     * Builds the coupon option detail.
     *
     * @param gid the gid
     * @param rsp the rsp
     * @throws ActivityException the activity exception
     */
    private void buildCouponOptionDetail(Long gid, PrizeDteailRsp rsp) throws ActivityException {

        DubboResult<AdvertCouponGoodsDto> result = remoteAdvertCouponGoodsBackendService.find(gid);
        if (!result.isSuccess()) {
            throw new ActivityException(ErrorCode.E0700001);
        }
        AdvertCouponGoodsDto couponDto = result.getResult();
        // 标题
        rsp.setTitle(null == couponDto.getCouponName() ? "" : couponDto.getCouponName());

        // 图片
        String image = "";
        String banner = couponDto.getBannerPng();
        if (StringUtils.isNotBlank(banner) && banner.contains(",")) {
            String[] img = banner.split(",");
            image = img[0];
        } else if (banner != null) {
            image = banner;
        }
        rsp.setImg(image);

        // 描述
        StringBuilder description = new StringBuilder(256);
        String remark = couponDto.getCouponRemark();
        if (remark != null) {
            String[] desc = remark.split("\n");
            for (String str : desc) {
                if (str.startsWith("###")) {
                    description.append("<h4>" + str.substring(3) + "</h4>");
                } else {
                    description.append(str);
                }
            }
        }
        String descriptionStr = description.toString().replaceAll("\"", "'");
        rsp.setDescription(descriptionStr);
    }

    /**
     * Builds the nothing option detail.
     *
     * @param dto the dto
     * @param rsp the rsp
     */
    private void buildNothingOptionDetail(ActivityOptionDto dto, PrizeDteailRsp rsp) {
        rsp.setTitle(dto.getTitle());
        rsp.setImg(dto.getDetailImg());
        rsp.setDescription(dto.getDetailDesc());
    }

    /**
     * 查询活动、流量引导页奖项
     *
     * @param req the req
     * @param consumer the consumer
     * @return the record list
     * @throws ActivityException the activity exception
     */
    @Override
    public PrizeRecordsRsp<RecordGeneralVO> getRecordList(OptionListReq req, UserAccount consumer, HttpServletRequest request) throws ActivityException {
        // 1、得到直投页的活动
        ActivityOrderReq activityOrderReq = new ActivityOrderReq();
        activityOrderReq.setConsumerId(consumer.getUserId());
        try {
            List<IDReq> idReqList = Lists.newArrayList();
            if (req.isGuidePage()) {
                idReqList = guidePageIDReqCache.get(req);
                if (CollectionUtils.isEmpty(idReqList)) {
                    return new PrizeRecordsRsp<>(0, Lists.newArrayList(), 0, 50);
                }
            }
            activityOrderReq.setIdReqList(idReqList);
        } catch (Exception e) {
            //异常后降级查询所有奖项
            activityOrderReq.setIdReqList(Lists.newArrayList());
        }
        activityOrderReq.setRowStart(req.getRowStart());
        activityOrderReq.setPageSize(req.getPageSize());
        PageDto<ActivityOrderDto> result = remoteActivityOrderService.selectByFilter(activityOrderReq);
        PrizeRecordsRsp<RecordGeneralVO> rsp = new PrizeRecordsRsp<>(req.getCurrentPage(), req.getPageSize());
        List<RecordGeneralVO> recordList = new ArrayList<>(req.getPageSize());
        List<ActivityOrderDto> orderDto = result.getList();

        Map<String, AlipayOrderDto> alipayOrderMap = EntityUtil.transf(activityOrderService.selectAlipayRecord(RequestLocal.get().getDeviceId()), AlipayOrderDto::getOrderId);
        int position = 1;
        Long directpage = this.directPageSourceService.get(consumer.getUserId());

        buildRecordGeneralVO(consumer, request, recordList, orderDto, alipayOrderMap, position, directpage);

        //客服信息模版-我的奖品
        ContactPlateDto contactPlateDto = contactPlateService.getDtoByHost(request.getHeader("host"));
        if (contactPlateDto != null) {
            PrizeRecordsRsp.ContactInfo contactInfo = rsp.createContactInfo();
            contactInfo.setMineOptionPhone(contactPlateDto.getMineOptionPhone());
            contactInfo.setMineOptionQq(contactPlateDto.getMineOptionQq());
            contactInfo.setIsOpenMineOnline(contactPlateDto.getIsOpenMineOnline());
            contactInfo.setIsOpenMineOption(contactPlateDto.getIsOpenMineOption());
        }
        // 2.组装响应
        rsp.setEmbedData(ActivityEmbed.buildMineRecordListEmbed(consumer, request.getHeader("host"), null));
        rsp.setList(recordList);
        rsp.setTotalCount(result.getTotalCount());
        return rsp;
    }

    /**
     * 构建奖项 RecordGeneralVO
     *
     * @param consumer
     * @param request
     * @param recordList
     * @param orderDto
     * @param alipayOrderMap
     * @param position
     * @param directpage
     */
    private void buildRecordGeneralVO(UserAccount consumer, HttpServletRequest request, List<RecordGeneralVO> recordList, List<ActivityOrderDto> orderDto, Map<String, AlipayOrderDto> alipayOrderMap, int position, Long directpage) {
        for (ActivityOrderDto order : orderDto) {
            RecordGeneralVO record;
            Long finalDirectpage = null;
            if (ActivityOptionType.TYPE_ALIPAY.getCode().equals(order.getPrizeType())
                    || ActivityOptionType.TYPE_PHYSICAL.getCode().equals(order.getPrizeType())
                    || ActivityOptionType.TYPE_VIRTUAL.getCode().equals(order.getPrizeType())
                    || ActivityOptionType.TYPE_QB.getCode().equals(order.getPrizeType())
                    || ActivityOptionType.TYPE_BILL.getCode().equals(order.getPrizeType())) {
                AlipayOrderDto alipayOrderDto = alipayOrderMap.get(order.getOrderId());
                if (null == alipayOrderDto) {
                    continue;
                }
                record = getSpecialRecord(request, order, alipayOrderDto);
            } else {
                //构造优惠券
                record = getCouponData(order, request);
                finalDirectpage = directpage;
            }
            //埋点
            if (record.getRemainDay() > -1) {
                record.setStmInfos(ActivityEmbed.buildMineReordEmbed(consumer, order, position, request.getHeader("host"), finalDirectpage));
                position++;
            }
            recordList.add(record);
        }
    }

    /**
     * 得到直投页活动ID列表
     *
     * @param req
     * @return
     * @throws ActivityException
     */
    private List<IDReq> getGuidePagPageIdList(OptionListReq req) throws ActivityException {
        List<IDReq> idReqList = Lists.newArrayList();
        if (req.isGuidePage()) {
            GuidePageDto guidePageDto = guidePageService.getGuidePage(req.getPageId());
            if (guidePageDto != null) {
                List<GuidePageRelationDto> guidePageRelationDtoList = guidePageDto.getActivitys();
                //构建主会场活动插件参数
                buildMainMeetBlock(idReqList, guidePageRelationDtoList);
                //构建直投页活动插件参数
                buildDirectPageBlock(idReqList, req.getPageId());
                if (!CollectionUtils.isEmpty(idReqList)) {
                    idReqList = idReqList.stream().filter(e -> e.getId() != null && !e.getId().equals(0l)).collect(Collectors.toList());
                }
            }
        }
        return idReqList;
    }

    private void buildDirectPageBlock(List<IDReq> idReqList, Long pageId) {
        DubboResult<List<GuidePageBlockDto>> result = remoteGuidePageService.selectDirectBlock(pageId);
        List<GuidePageBlockDto> guidePageBlockDtoList = result.getResult();
        if (!CollectionUtils.isEmpty(guidePageBlockDtoList)) {
            guidePageBlockDtoList.forEach(e -> {
                if (e.getBlockType() != null && !StringUtils.isEmpty(e.getRelationIds()) && DirectBlockType.ACTIVITY_BLOCK2.getType().equals(e.getBlockType())) {
                    IDReq idReq = new IDReq();
                    idReq.setId(Long.valueOf(e.getRelationIds().replace(",", "")));
                    idReq.setIdType(IdType.ACTIVITY.getType());
                    idReqList.add(idReq);
                }
                if (e.getBlockType() != null && !StringUtils.isEmpty(e.getRelationIds()) && DirectBlockType.PLUGIN_BLOCK.getType().equals(e.getBlockType())) {
                    IDReq idReq = new IDReq();
                    idReq.setId(Long.valueOf(e.getRelationIds().replace(",", "")));
                    idReq.setIdType(IdType.PLUGIN.getType());
                    idReqList.add(idReq);
                }
            });
        }
    }

    private void buildMainMeetBlock(List<IDReq> idReqList, List<GuidePageRelationDto> guidePageRelationDtoList) {
        if (!CollectionUtils.isEmpty(guidePageRelationDtoList)) {
            guidePageRelationDtoList.forEach(e -> {
                if (e.getIdType() != null && (e.getIdType().equals(IdType.ACTIVITY.getType()) || e.getIdType().equals(IdType.PLUGIN.getType()))) {
                    IDReq idReq = new IDReq();
                    idReq.setId(e.getActivityId());
                    idReq.setIdType(e.getIdType());
                    idReqList.add(idReq);
                }
            });
        }
    }

    public RecordGeneralVO getSpecialRecord(HttpServletRequest request, ActivityOrderDto order, AlipayOrderDto alipayOrderDto) {
        if (AlipayType.isVirtualTicket(alipayOrderDto.getAlipayType())) {
            return getTicketRecord(order, alipayOrderDto);
        }
        RecordGeneralVO record = new RecordGeneralVO();
        Integer status = alipayOrderDto.getStatus();
        record.setPrizeType(order.getPrizeType());
        record.setOrderId(order.getOrderId());
        if (StringUtils.isNotBlank(order.getCouponData())) {
            record.setTitle(order.getCouponData(ActivityOrderDto.PrizeInfo.TITLE));
            record.setThumbnailPng(order.getCouponData(ActivityOrderDto.PrizeInfo.BANNER_IMAGE));//225*140
        } else {
            //TODO 对旧数据做的兼容，等20171107日之前的支付宝订单被清理之后就可以去掉
            PrizeDto prize = prizeService.selectPrizeById(order.getGid());
            record.setTitle(prize.getTitle());
            record.setThumbnailPng(prize.getBannerImage());
        }
        record.setStatus(status);
        record.setStatusTips(AlipayOrderStatus.getEnumByStatus(status).getUserTip());
        if (AlipayOrderStatus.DEALING.getStatus().equals(alipayOrderDto.getStatus())
                || AlipayOrderStatus.CONSUMER_ERROR.getStatus().equals(alipayOrderDto.getStatus())) {
            record.setRemainTime(getRemainTime(record, order.getGmtCreate()));
        }
        record.setRemainDay(0);
        if (AlipayOrderStatus.SUCCESS.getStatus().equals(record.getStatus()) || AlipayOrderStatus.FORCE_CLOSE.getStatus().equals(record.getStatus())) {
            record.setRemainDay(0);
        } else if (AlipayOrderStatus.OVERDUE.getStatus().equals(record.getStatus())) {
            record.setRemainDay(-1);
        }
        record.replaceDomain(DomainUtil.getCurrentYunDomain(request));
        return record;
    }

    private RecordGeneralVO getTicketRecord(ActivityOrderDto order, AlipayOrderDto alipayOrderDto) {
        RecordGeneralVO record = new RecordGeneralVO();
        record.setOrderId(order.getOrderId());
        record.setTitle(order.getCouponData(ActivityOrderDto.PrizeInfo.TITLE));
        record.setThumbnailPng(order.getCouponData(ActivityOrderDto.PrizeInfo.BANNER_IMAGE));//225*140
        record.setEndValid(alipayOrderDto.getCoupon().getValidEndDate());
        record.setRemainDay(DateUtils.daysBetween(new Date(), new DateTime(record.getEndValid()).toDate()));
        return record;
    }

    /**
     * 获取剩余时间
     *
     * @param createTime
     * @return
     */
    private String getRemainTime(RecordGeneralVO record, Date createTime) {
        int time = Hours.hoursBetween(new DateTime(), new DateTime(createTime).dayOfMonth().addToCopy(1)).getHours();
        if (time == 0) {
            time = Minutes.minutesBetween(new DateTime(), new DateTime(createTime).dayOfMonth().addToCopy(1)).getMinutes();
            if (time < 0) {
                record.setStatus(AlipayOrderStatus.OVERDUE.getStatus());
            }
            return time + "分钟";
        }
        return time + "小时";
    }

    @Override
    public ActivityOptionRsp getActivityOption(ActivityOptionReq req, HttpServletRequest request) throws ActivityException {
        long activityId = req.getActivityId();
        ActivityOptionRsp rsp = new ActivityOptionRsp();

        // 查询活动
        TuiaActivityDto activity = this.activityService.getActivityById(activityId);

        if (activity == null) {
            throw new ActivityException(ErrorCode.E0400001);
        }

        // 奖项
        List<ActivityOptionDto> options = this.activityService.selectActivityOptionsFromCache(activityId);
        rsp.setOptions(options);

        // 参与次数限制类型
        rsp.setLimitType(LimitType.getTypeByCode(activity.getLimitScope()));

        // 剩余参与次数
        int limitTimes = activity.getLimitCount()
                - this.activityService.getConsumerActivityDojoinCache(activityId, req.getConsumerId());
        rsp.setLimitTimes(limitTimes < 0 ? 0 : limitTimes);
        rsp.replaceDomain(DomainUtil.getCurrentYunDomain(request));

        //客服信息模版-奖品点击开关
        ContactPlateDto contactPlateDto = contactPlateService.getDtoByHost(request.getHeader("host"));
        rsp.setIsOpenPrizeInfo(contactPlateDto == null ? false : contactPlateDto.getIsOpenPrizeInfo());

        rsp.setEmbedData(getActivityEmbed(req.getAppId(), req.getConsumerId(), activity, request));
        return rsp;
    }

    @Override
    public ActivityLimitTimesRsp getLimitTimes(ActivityOptionReq req) throws ActivityException {
        // 查询活动
        TuiaActivityDto activity = this.activityService.getActivityById(req.getActivityId());

        if (activity == null) {
            throw new ActivityException(ErrorCode.E0400001);
        }

        ActivityLimitTimesRsp rsp = new ActivityLimitTimesRsp();

        // 参与次数限制类型
        rsp.setLimitType(LimitType.getTypeByCode(activity.getLimitScope()));

        // 剩余参与次数
        int limitTimes = activity.getLimitCount()
                - this.activityService.getConsumerActivityDojoinCache(req.getActivityId(), req.getConsumerId());

        rsp.setLimitTimes(limitTimes);
        return rsp;
    }

    /*
    加载客服信息
     */
    private void setContacPlate(String host, ModelAndView model) throws ActivityException {
        //客服信息模版-奖品点击开关
        ContactPlateDto contactPlateDto = contactPlateService.getDtoByHost(host);
        String ruleInfo = "";
        Boolean isOpenPrizeInfo = false;
        if (contactPlateDto != null) {
            ruleInfo = Optional.ofNullable(contactPlateDto.getRuleInfo()).orElse("");
            isOpenPrizeInfo = contactPlateDto.getIsOpenPrizeInfo();
        }
        model.addObject("contaction", ruleInfo);
        model.addObject("isOpenPrizeInfo", isOpenPrizeInfo);
    }


    /*
    加载活动奖项信息
     */
    private void setActivityOption(TuiaActivityDto activity, Long slotId, String domain, ModelAndView model,int joinTimes) {
        List<ActivityOptionDto> options = this.activityService.selectActivityOptionsFromCache(activity.getId());
        // 域名替换
        if (CollectionUtils.isNotEmpty(options)) {
            options.forEach(dto -> {
                dto.setImage(DomainUtil.replaceDomain(dto.getImage(), domain));
                dto.setDetailImg(DomainUtil.replaceDomain(dto.getDetailImg(), domain));
            });
        }

        model.addObject("options", JSONObject.toJSONString(options));
        model.addObject("limitType", LimitType.getTypeByCode(activity.getLimitScope()));

        //参与次数

        // 剩余参与次数
        int limitTimes = activity.getLimitCount() - joinTimes;
        model.addObject("limitTimes", limitTimes < 0 ? 0 : limitTimes);
        model.addObject("isPullDown", activityService.isPullDown(slotId, activity.getId(), joinTimes));

    }
    /*
    配置埋点信息
     */
    private void setEmbedData(TuiaActivityDto activity, Long appId, Long consumerId, HttpServletRequest request, ModelAndView model) {
        JSONObject embedData = new JSONObject();
        //构建埋点数据
        //1.规则-点击
        String ruleDpm = DpmInfo.getDpmInfo(appId, Constants.DPM.DPM_B_3, Constants.DPM.DPM_C_7, Constants.DPM.DPM_D_0);
        String ruleDcm = DpmInfo.dcmInfo(Constants.DCM.DCM_A_1014, (long) Constants.DCM.DCM_B_0, activity.getActivityType(), activity.getId());
        //2.我的奖品-点击
        String optionsDpm = DpmInfo.getDpmInfo(appId, Constants.DPM.DPM_B_3, Constants.DPM.DPM_C_2, Constants.DPM.DPM_D_0);
        String optionsDcm = DpmInfo.dcmInfo(Constants.DCM.DCM_A_1010, Long.valueOf(Constants.DCM.DCM_B_0), Constants.DCM.DCM_C_0, Long.valueOf(Constants.DCM.DCM_D_0));
        //3.活动说明-曝光
        String ruleExposureDpm = DpmInfo.getDpmInfo(appId, Constants.DPM.DPM_B_56, Constants.DPM.DPM_C_1, Constants.DPM.DPM_D_0);
        String ruleExposureDcm = DpmInfo.dcmInfo(Constants.DCM.DCM_A_1014, Long.valueOf(Constants.DCM.DCM_B_0), activity.getActivityType(), activity.getId());
        //4.活动说明展开更多-点击
        String ruleMoreDpm = DpmInfo.getDpmInfo(appId, Constants.DPM.DPM_B_56, Constants.DPM.DPM_C_1, Constants.DPM.DPM_D_2);
        String ruleMoreDcm = DpmInfo.dcmInfo(Constants.DCM.DCM_A_1014, Long.valueOf(Constants.DCM.DCM_B_0), activity.getActivityType(), activity.getId());
        //5.活动说明收起更多-点击
        String ruleLessDpm = DpmInfo.getDpmInfo(appId, Constants.DPM.DPM_B_56, Constants.DPM.DPM_C_1, Constants.DPM.DPM_D_3);
        String ruleLessDcm = DpmInfo.dcmInfo(Constants.DCM.DCM_A_1014, Long.valueOf(Constants.DCM.DCM_B_0), activity.getActivityType(), activity.getId());
        //6.活动说明关闭-点击
        String ruleCloseDpm = DpmInfo.getDpmInfo(appId, Constants.DPM.DPM_B_56, Constants.DPM.DPM_C_1, Constants.DPM.DPM_D_1);
        String ruleCloseDcm = DpmInfo.dcmInfo(Constants.DCM.DCM_A_1014, Long.valueOf(Constants.DCM.DCM_B_0), activity.getActivityType(), activity.getId());

        //设置埋点数据+埋点地址
        embedData.put("st_info_rule_click", DpmInfo.setStActivityClickJSON(appId, consumerId, ruleDpm, ruleDcm, "//" + request.getHeader("host")));
        embedData.put("st_info_options_click", DpmInfo.setStActivityClickJSON(appId, consumerId, optionsDpm, optionsDcm, "//" + request.getHeader("host")));
        embedData.put("st_info_rule_exposure", DpmInfo.setStActivityInfoJSON(appId, consumerId, ruleExposureDpm, ruleExposureDcm, "//" + request.getHeader("host"),null));
        embedData.put("st_info_rule_more_click", DpmInfo.setStActivityClickJSON(appId, consumerId, ruleMoreDpm, ruleMoreDcm, "//" + request.getHeader("host")));
        embedData.put("st_info_rule_less_click", DpmInfo.setStActivityClickJSON(appId, consumerId, ruleLessDpm, ruleLessDcm, "//" + request.getHeader("host")));
        embedData.put("st_info_rule_close_click", DpmInfo.setStActivityClickJSON(appId, consumerId, ruleCloseDpm, ruleCloseDcm, "//" + request.getHeader("host")));

        model.addObject("embedData", embedData.toJSONString());
    }


    /**
     * 活动页添加埋点
     *
     * @param appId
     * @param consumerId
     * @param activityDto
     * @param request
     */
    private Map<String, String> getActivityEmbed(Long appId, Long consumerId, TuiaActivityDto activityDto, HttpServletRequest request) {
        Map<String, String> embedData = new HashMap<>();
        //构建埋点数据
        //1.规则-点击
        String ruleDpm = DpmInfo.getDpmInfo(appId, Constants.DPM.DPM_B_3, Constants.DPM.DPM_C_7, Constants.DPM.DPM_D_0);
        String ruleDcm = DpmInfo.dcmInfo(Constants.DCM.DCM_A_1014, (long) Constants.DCM.DCM_B_0, activityDto.getActivityType(), activityDto.getId());
        //2.我的奖品-点击
        String optionsDpm = DpmInfo.getDpmInfo(appId, Constants.DPM.DPM_B_3, Constants.DPM.DPM_C_2, Constants.DPM.DPM_D_0);
        String optionsDcm = DpmInfo.dcmInfo(Constants.DCM.DCM_A_1010, Long.valueOf(Constants.DCM.DCM_B_0), Constants.DCM.DCM_C_0, Long.valueOf(Constants.DCM.DCM_D_0));
        //3.活动说明-曝光
        String ruleExposureDpm = DpmInfo.getDpmInfo(appId, Constants.DPM.DPM_B_56, Constants.DPM.DPM_C_1, Constants.DPM.DPM_D_0);
        String ruleExposureDcm = DpmInfo.dcmInfo(Constants.DCM.DCM_A_1014, Long.valueOf(Constants.DCM.DCM_B_0), activityDto.getActivityType(), activityDto.getId());
        //4.活动说明展开更多-点击
        String ruleMoreDpm = DpmInfo.getDpmInfo(appId, Constants.DPM.DPM_B_56, Constants.DPM.DPM_C_1, Constants.DPM.DPM_D_2);
        String ruleMoreDcm = DpmInfo.dcmInfo(Constants.DCM.DCM_A_1014, Long.valueOf(Constants.DCM.DCM_B_0), activityDto.getActivityType(), activityDto.getId());
        //5.活动说明收起更多-点击
        String ruleLessDpm = DpmInfo.getDpmInfo(appId, Constants.DPM.DPM_B_56, Constants.DPM.DPM_C_1, Constants.DPM.DPM_D_3);
        String ruleLessDcm = DpmInfo.dcmInfo(Constants.DCM.DCM_A_1014, Long.valueOf(Constants.DCM.DCM_B_0), activityDto.getActivityType(), activityDto.getId());
        //6.活动说明关闭-点击
        String ruleCloseDpm = DpmInfo.getDpmInfo(appId, Constants.DPM.DPM_B_56, Constants.DPM.DPM_C_1, Constants.DPM.DPM_D_1);
        String ruleCloseDcm = DpmInfo.dcmInfo(Constants.DCM.DCM_A_1014, Long.valueOf(Constants.DCM.DCM_B_0), activityDto.getActivityType(), activityDto.getId());

        //设置埋点数据+埋点地址
        embedData.put("st_info_rule_click", DpmInfo.setStActivityClick(appId, consumerId, ruleDpm, ruleDcm, "//" + request.getHeader("host"),null));
        embedData.put("st_info_options_click", DpmInfo.setStActivityClick(appId, consumerId, optionsDpm, optionsDcm, "//" + request.getHeader("host"),null));
        embedData.put("st_info_rule_exposure", DpmInfo.setStActivityInfo(appId, consumerId, ruleExposureDpm, ruleExposureDcm, "//" + request.getHeader("host"),null));
        embedData.put("st_info_rule_more_click", DpmInfo.setStActivityClick(appId, consumerId, ruleMoreDpm, ruleMoreDcm, "//" + request.getHeader("host"),null));
        embedData.put("st_info_rule_less_click", DpmInfo.setStActivityClick(appId, consumerId, ruleLessDpm, ruleLessDcm, "//" + request.getHeader("host"),null));
        embedData.put("st_info_rule_close_click", DpmInfo.setStActivityClick(appId, consumerId, ruleCloseDpm, ruleCloseDcm, "//" + request.getHeader("host"),null));

        return embedData;
    }

    /**
     * Gets the coupon data.
     *
     * @param order the order
     * @return the coupon data
     */
    private RecordGeneralVO getCouponData(ActivityOrderDto order, HttpServletRequest request) {
        RecordGeneralVO record = new RecordGeneralVO();
        record.setOrderId(order.getOrderId());
        JSONObject jsonObject = JSON.parseObject(order.getCouponData());
        if (null != jsonObject) {
            record.setTitle(jsonObject.getString(Constants.VALUENAME.TITLE));
            record.setThumbnailPng(jsonObject.getString(Constants.VALUENAME.THUMBNAIL_PNG));
            record.setEndValid(jsonObject.getString(Constants.VALUENAME.END_VALID));
            record.setRemainDay(DateUtils.daysBetween(new Date(), new DateTime(record.getEndValid()).toDate()));
        }
        record.replaceDomain(DomainUtil.getCurrentYunDomain(request));
        return record;
    }

    /**
     * Gets the record.
     *
     * @param orderId the order id
     * @param request the request
     * @return the record
     * @throws ActivityException the activity exception
     */
    @Override
    public RecordDetailVO getRecord(String orderId, UserAccount consumer, HttpServletRequest request) throws ActivityException {
        String host = request.getHeader("host");

        // 1.根据consumerId+orderId查询具体订单
        DubboResult<ActivityOrderDto> result = remoteActivityOrderService.selectByOrderIdAndConsumerId(orderId,
                consumer.getUserId());
        if (!result.isSuccess()) {
            logger.info("get order from tuia-activity-center fail.");
            throw new ActivityException(ErrorCode.E0400008.geteCode(), "获取兑换记录失败");
        }

        // 2.根据订单Id查询引擎，获取中奖优惠券详情
        ActivityOrderDto dto = result.getResult();
        RecordDetailVO recordDetail = new RecordDetailVO();
        Long directpage = null;

        if (ActivityOptionType.TYPE_ALIPAY.getCode().equals(dto.getPrizeType())
                || ActivityOptionType.TYPE_PHYSICAL.getCode().equals(dto.getPrizeType())
                || ActivityOptionType.TYPE_VIRTUAL.getCode().equals(dto.getPrizeType())
                || ActivityOptionType.TYPE_QB.getCode().equals(dto.getPrizeType())
                || ActivityOptionType.TYPE_BILL.equalsCode(dto.getPrizeType())
                ) {

            AlipayOrderDto alipayOrderDto = activityOrderService.selectAlipayOrder(dto.getOrderId());
            ActivityOptionDto optionDto = activityService.selectActivityOption(alipayOrderDto.getPrizeId());
            PrizeDto prizeDto = prizeService.selectPrizeById(optionDto.getPrizeId());

            recordDetail.setBannerPng(optionDto.getImage());//实物取250*250,支付宝不用图片
            recordDetail.setActivityId(dto.getActivityId());
            recordDetail.setAlipayAccount(alipayOrderDto.getAliAccount());
            recordDetail.setAlipayName(alipayOrderDto.getAliName());
            recordDetail.setShippingAddress(alipayOrderDto.getShippingAddress());
            recordDetail.setExpress(alipayOrderDto.getExpress());
            recordDetail.setTitle(alipayOrderDto.getPrizeTitle());
            recordDetail.setExpressNumber(alipayOrderDto.getExpressNumber());
            if (null != alipayOrderDto.getAwardAmount()) {
                recordDetail.setAmount(ActivityOptionType.TYPE_QB.getCode().equals(dto.getPrizeType()) ? String.valueOf(alipayOrderDto.getAwardAmount() / prizeDto.getPrizeValue()) : MathUtil.fen2Yuan(alipayOrderDto.getAwardAmount()));
            }
            Integer status = alipayOrderDto.getStatus();
            recordDetail.setStatus(status);
            recordDetail.setStatusTips(AlipayOrderStatus.getEnumByStatus(status).getUserTip());

            //配置虚拟奖品信息
            if (ActivityOptionType.TYPE_VIRTUAL.getCode().equals(dto.getPrizeType())) {
                setVirtualRecoedExt(recordDetail, alipayOrderDto, optionDto, host, request);
            }
        } else {
            Long slotId =null;
            if (StringUtils.isNotBlank(RequestLocal.get().getSlotId())) {
                slotId = Long.valueOf(RequestLocal.get().getSlotId());
            }
            QueryAdvertRsp queryAdvertRsp = luckBagService.queryAdvert(consumer.getUserId(), orderId, 1, slotId);
            if (null == queryAdvertRsp) {
                throw new ActivityException(ErrorCode.E0800001.geteCode(), "从引擎获取已中奖广告券失败");
            }
            String orderId4Engine = Constants.THE_PREFIX_ORDERID + orderId;
            // 3.组装兑换记录返回
            recordDetail = BeanUtils.copy(getCouponData(result.getResult(), request), RecordDetailVO.class);
            recordDetail.setCouponRemark(queryAdvertRsp.getCouponRemark());
            recordDetail.setBannerPng(queryAdvertRsp.getBannerPngUrl());
            recordDetail.setButtonText(queryAdvertRsp.getButtonText());
            recordDetail.setCodeContent(queryAdvertRsp.getCodeContent());
            recordDetail.setCodePasswd(queryAdvertRsp.getCodePasswd());
            recordDetail.setOrderId(dto.getOrderId());
            recordDetail.setActivityId(dto.getActivityId());

            directpage = this.directPageSourceService.get(consumer.getUserId());

            String dcm = DpmInfo.getDcmInfo(queryAdvertRsp.getAdvertId(), queryAdvertRsp.getMaterialId());
            String stInfo = DpmInfo.setStInfo("//" + host, RequestLocal.get().getAppId(), consumer.getUserId(),
                    orderId4Engine, queryAdvertRsp.getAdvertId(), queryAdvertRsp.getMaterialId(),
                    dto.getActivityId(), null, dcm, null, null, null, CouponSource.ACTIVITY.getCode(), dto.getActivityType(), null,directpage);

            recordDetail.setStmInfo(stInfo);
            buildButtonUrl(request, queryAdvertRsp, recordDetail);
        }

        //配置客服信息模版-详情页
        configContactPlate(recordDetail, host);
        //配置埋点信息
        recordDetail.setStmInfos(ActivityEmbed.buildRecordEmbed(consumer, host, dto,directpage));
        return recordDetail;
    }

    //配置客服信息模版-详情页
    private void configContactPlate(RecordDetailVO recordDetail, String host) throws ActivityException {
        //客服信息模版-详情页
        ContactPlateDto contactPlateDto = contactPlateService.getDtoByHost(host);
        if (contactPlateDto != null) {
            RecordDetailVO.DetailContactInfo detailContactInfo = recordDetail.createDetailContactInfo();
            detailContactInfo.setIsOpenOptionDetail(contactPlateDto.getIsOpenOptionDetail());
            detailContactInfo.setOptionDetailPhone(contactPlateDto.getOptionDetailPhone());
        }
    }

    /**
     * 配置虚拟奖品-详情页额外配置信息
     *
     * @param recordDetail
     * @param alipayOrderDto
     */
    private void setVirtualRecoedExt(RecordDetailVO recordDetail, AlipayOrderDto alipayOrderDto, ActivityOptionDto optionDto, String host, HttpServletRequest request) {

        PrizeDto prizeDto = prizeService.selectPrizeById(optionDto.getPrizeId());
        recordDetail.setCouponRemark(prizeDto.getDescription());
        recordDetail.setCouponDetailRemark(prizeDto.getDetailDesc());
        recordDetail.setOrderId(alipayOrderDto.getOrderId());
        recordDetail.setBannerPng(prizeDto.getDetailImage());

        //获取dsm
        String dsm = buildDsm(request);
        if (AlipayType.isVirtualApi(alipayOrderDto.getAlipayType())) {
            recordDetail.setOptionWinnerInfos(alipayOrderDto.getContextArray());
            recordDetail.setAwardAmount(alipayOrderDto.getPrizeWorth());
            recordDetail.setSubType(AlipayType.VIRTUAL_API.getType());
            recordDetail.setValueUnit(prizeDto.getApiRechargeDto().getValueUnit());
        } else if (AlipayType.isVirtualTicket(alipayOrderDto.getAlipayType())) {
            recordDetail.setSubType(AlipayType.VIRTUAL_TICKET.getType());

            if (alipayOrderDto.getCoupon() != null) {
                recordDetail.setCodeContent(alipayOrderDto.getCoupon().getCouponsCode());
                recordDetail.setCodePasswd(alipayOrderDto.getCoupon().getCouponsPwd());
                recordDetail.setEndValid(alipayOrderDto.getCoupon().getValidEndDate());
                recordDetail.setLinkUrl(alipayOrderDto.getCoupon().getLinkInfo());
                recordDetail.setRemainDay(DateUtils.daysBetween(new Date(), new DateTime(recordDetail.getEndValid()).toDate()));
            }

            if (prizeDto.getCouponsCodeDto() != null) {
                recordDetail.setCouponInfo(prizeDto.getCouponsCodeDto().getUseInfo());
            }

            if (AlipayType.VIRTUAL_TICKET_2.getType().equals(alipayOrderDto.getAlipayType())) {
                recordDetail.setShowUse(recordDetail.getRemainDay() >= 0);
                recordDetail.setButtonText("马上使用");
            }

        } else if (AlipayType.VIRTUAL_ACCOUNT.getType().equals(alipayOrderDto.getAlipayType())) {
            recordDetail.setOptionWinnerInfos(alipayOrderDto.getContextArray());
            recordDetail.setSubType(AlipayType.VIRTUAL_ACCOUNT.getType());
        } else if (AlipayType.VIRTUAL_RED_PACKET.getType().equals(alipayOrderDto.getAlipayType())) {
            recordDetail.setSubType(AlipayType.VIRTUAL_RED_PACKET.getType());
            IndexReq req = new IndexReq();
            req.setHost(host);
            req.setLogin(LoginType.NORMAL.getCode());
            req.setSlotId(alipayOrderDto.getSlotId());
            req.setDeviceId(alipayOrderDto.getDeviceId());
            req.setAppKey(RequestLocal.get().getAppKey());//许确认
            req.setActivityId(alipayOrderDto.getActivityId());
            req.setDsm(dsm);
            req.setDcm(DcmBuilder.directFixedBlockBuild(prizeDto.getRedPacket().getPageId()));
            recordDetail.setLinkUrl(PathUtil.getGuidePageUrl(prizeDto.getRedPacket().getPageId(), req, PageType.DIRECT.getCode()));
            recordDetail.setShowUse(true);
            recordDetail.setButtonText("一起拿红包");
        }
    }

    /*
     我的奖品页 后置页面的dsm
     */
    private String buildDsm(HttpServletRequest request) {
        try {
            String dsm = request.getParameter(Constants.KEY.DSM);
            if (StringUtils.isNotBlank(dsm)) {
                return DsmBuilder.recordBuild(dsm);
            }
        } catch (Exception e) {
            logger.warn("build dsm error", e);
        }
        return null;
    }

    /**
     * 是否出中奖公示
     *
     * @param slotDto
     * @return
     */
    private boolean isPublicNotice(SlotDto slotDto) {
        return Integer.valueOf(PlugBuoyConfigDto.PRIZEPUBLICITY_OPEN).equals(slotDto.getPlugBuoyConfigDto().getIsPrizePublicity());
    }

    /**
     * 是否优先请求响应式插件
     *
     * @param slotDto
     * @return
     */
    private boolean isPriority(SlotDto slotDto) {
        return Integer.valueOf(PlugBuoyConfigDto.RSP_PLUG_PRIORITY).equals(slotDto.getPlugBuoyConfigDto().getRspPlugLevel());
    }

    private boolean isShowTiming(SlotDto slotDto) {
        return Integer.valueOf(PlugBuoyConfigDto.TIMING_PLUG_ENABLE).equals(slotDto.getPlugBuoyConfigDto().getTimingPlugStatus());
    }

    private boolean isShowRsp(SlotDto slotDto) {
        return Integer.valueOf(PlugBuoyConfigDto.RSP_PLUG_ENABLE).equals(slotDto.getPlugBuoyConfigDto().getRspPlugStatus());
    }

    private void isShowSomeThing(TuiaActivityDto activityDto, Long slotId, UserAccount consumer, ModelAndView model,int joinTimes, long styleType) throws ActivityException {
        boolean isShowBuoy = false;
        boolean isShowTiming = false;
        boolean isShowRsp = false;
        boolean isPriority = false;
        boolean isRecom = false;
        boolean keFuType = false;
        boolean isPublicNotice = false;
        Integer isPrizeRecommend = 1;
        //海外标识
        Integer overseas = 0;

        if (slotId != null) {
            Optional<SlotDto> optional = this.slotService.getSlot(slotId);
            if (optional.isPresent()) {
                SlotDto slotDto = optional.get();
                isPrizeRecommend = slotDto.getPlugBuoyConfigDto().getIsPrizeRecommend();
                isShowBuoy = this.activityOrderService.isShowBuoy(activityDto, slotDto, consumer.getUserId(), joinTimes, styleType);
                if (slotDto.getPlugBuoyConfigDto() != null) {
                    isShowTiming = isShowTiming(slotDto);
                    isShowRsp = isShowRsp(slotDto);
                    isPriority = isPriority(slotDto);
                    isPublicNotice = isPublicNotice(slotDto);
                }
                //是否展示推荐位
                isRecom = slotDto.getIsRecommend();
                //是否展示在线客服按钮
                keFuType = 1 == slotDto.getShowService();
            }
        }
        if(consumer.getAppId() != null) {
            Optional<MediaAppDto> optional = appService.getMediaApp(consumer.getAppId());
            if(optional.isPresent()) {
                overseas = optional.get().getOverseas();
            }
        }
        String catchSpeed = systemConfigService.getSystemConfig("tuia_catch_speed");
        model.addObject("isPrizeRecommend", Integer.valueOf(1).equals(isPrizeRecommend));
        model.addObject("isShowBuoy", isShowBuoy);
        model.addObject("isShowTiming", isShowTiming);
        model.addObject("isShowRsp", isShowRsp);
        model.addObject("isPriority", isPriority);
        model.addObject("isShowRecommend", isRecom);
        model.addObject("kefuType", keFuType);
        model.addObject("isPublicNotice", isPublicNotice);
        model.addObject("isCatchSpeed", Boolean.parseBoolean(catchSpeed));//前端测试脚本开关，后续删
        model.addObject(Constants.VALUENAME.OVERSEAS, overseas);
    }

    /**
     * Index.
     *
     * @param req the req
     * @param consumer the consumer
     * @param request the request
     * @return the model and view
     * @throws ActivityException the activity exception
     */
    @Override
    public ModelAndView index(IndexReq req, UserAccount consumer, HttpServletRequest request) throws ActivityException, ExecutionException, BusinessException {
        /**
         * 割绳子
         *
         * 前端性能优化：减少接口请求
         *
         */
        String domain = DomainUtil.getCurrentYunDomain(request);
        String host = request.getHeader("host");

        // 新弹层逻辑

        // 活动皮肤ABtest 遗址
        //daYuService.activitySkinABTest(activitySkinDataDto, consumer.getUserId())

        // 1.查询并验证活动信息
        TuiaActivityDto activityDto = filterNull(activityService.getActivityById(req.getId()), ErrorCode.E0400004);

        // 查询皮肤信息
        ActivitySkinDataDto activitySkinDataDto = filterNull(activityService.selectActivitySkinByActivityId(req.getId(), req.getLogin()), ErrorCode.E0400004);

        // 2.组装页面初始数据
        ModelAndView model = tupleModelAndView(activityDto, req);

        // 2.0 设置分流字段
        // 2520为1~10的最小公倍数，也即可以任意均分
        long styleType = Math.abs(consumer.getUserId().hashCode()) % 2520 + 1;
        model.addObject("styleType", styleType);
        AccessLogFilter.putExPair("styleType", styleType);

        // 2.1 查询参与次数
        int joinTimes = this.activityService.getConsumerActivityDojoinCache(req.getId(), consumer.getUserId());

        // 3.设置是否需要展示浮标 等字段
        isShowSomeThing(activityDto, req.getSlotId(), consumer, model, joinTimes, styleType);

        // 4.设置弹层
        setLayer(activitySkinDataDto, model);

        // 5.set 皮肤
        setSkinConfig(activitySkinDataDto, domain, model, styleType);

        // 6.set 奖项信息
        setActivityOption(activityDto, req.getSlotId(), domain, model, joinTimes);

        // 7.set 客服信息
        setContacPlate(host, model);

        // 8.埋点信息
        setEmbedData(activityDto, consumer.getAppId(), consumer.getUserId(), request, model);


        // 9.增加地域日志
        AccessLogFilter.putExPair("area_code",this.slotService.findRegionByIp(req.getIp()));

        this.directPageSourceService.log(consumer.getUserId());

        model.addObject("slotId", req.getSlotId());
        model.addObject("host", DomainUtil.getHost(request));
        model.addObject("consumerId", consumer.getUserId());
        model.addObject("appId", consumer.getAppId());
        model.addObject("pageHost", "//" + host);

        return model;
    }

    /**
     * 根据概率计算新旧广告弹层
     * 并把isShowNew(true/false)
     * couponSkinId
     * 塞到vm中
     *
     * @param skinDataDto 活动皮肤dto
     * @param model
     */
    private void setLayer(ActivitySkinDataDto skinDataDto, ModelAndView model) {
        Integer newLayerRate = skinDataDto.getNewLayerRate() == null ? 0 : skinDataDto.getNewLayerRate();
        // 弹层随机数(0.0000000000000000 到100.0000000000000000)之间的随机数
        double randomNumber = Math.random() * 100;

        //a,b弹层，b可为null,newLayerRate 表示出b弹层的概率,b
        boolean isShowNew = true;
        Long bLayerId = skinDataDto.getbLayerId();
        if (bLayerId == null || newLayerRate < randomNumber) {
            isShowNew = false;
        }
        Long couponSkinId = isShowNew ? bLayerId : skinDataDto.getaLayerId();

        if (couponSkinId == null) {
            couponSkinId = this.skinService.selectDefaultLayerId();
        }
        if (couponSkinId == null) {
            couponSkinId = 1L;
        }

        //谢谢参与弹层
        String tuiaThanksLayer3Apps = systemConfigService.getSystemConfig("tuia_thanks_layer_3_apps");
        if(StringUtils.isNotBlank(tuiaThanksLayer3Apps)&&layer3Contains(tuiaThanksLayer3Apps)){
            model.addObject("thankLayerType",LayerSkinType.THANKS.getType());
        }
        else{
            model.addObject("thankLayerType", LayerSkinType.getRandomThanks());
        }


        model.addObject("isShowNew", isShowNew);
        model.addObject("couponSkinId", couponSkinId);
    }

    //判断appId是否是被配置为强制出Thanks类型的弹层
    private boolean layer3Contains(String tuiaThanksLayer3Apps) {
        List<String> strings = Splitter.on(";").trimResults().splitToList(tuiaThanksLayer3Apps);
        Long appId = RequestLocal.get().getAppId();
        if(appId!=null){
            return strings.contains(String.valueOf(appId));
        }
        return false;
    }

    /**
     * Index.
     *
     * @param req the req
     * @param consumer the consumer
     * @param request the request
     * @return the model and view
     * @throws ActivityException the activity exception
     */
    @Override
    public ModelAndView iframeIndex(IndexReq req, UserAccount consumer, HttpServletRequest request) throws ActivityException {

        ModelAndView model = new ModelAndView("activity/iframe");
        StringBuilder url = new StringBuilder();
        url.append("//" + request.getHeader("host"));
        url.append(Constants.PATH.ACTIVITY);
        url.append(Constants.PATH.NORMALINDEX);
        url.append(Constants.PARAM.ID).append(req.getId());

        url.append(Constants.PARAM.SLOTID).append(req.getSlotId());
        url.append(Constants.PARAM.LOGIN).append(req.getLogin());
        url.append(Constants.PARAM.DEVICEID).append(req.getDeviceId());
        url.append(Constants.PARAM.APPKEY).append(req.getAppKey());

        model.addObject("iframeUrl", url);
        return model;
    }

    /**
     * Tuple model and view.
     *
     * @param tuiaActivityDto the tuia activity dto
     * @param req the login
     * @return the model and view
     */
    private ModelAndView tupleModelAndView(TuiaActivityDto tuiaActivityDto, IndexReq req) throws BusinessException {
        if (tuiaActivityDto == null) {
            throw new BusinessException(ErrorCode.E0400001);
        }
        String subType = tuiaActivityDto.getSubType();
        ModelAndView model = new ModelAndView("activity/" + subType);
        model.addObject("activityId", tuiaActivityDto.getId());
        model.addObject("title", tuiaActivityDto.getTitle());
        model.addObject("isPreview", !LoginType.NORMAL.equalsCode(req.getLogin()));
        model.addObject("activityType", tuiaActivityDto.getActivityType());
        model.addObject("skinName", subType);
        return model;
    }

    /**
     * Index record.
     *
     * @param vmName the vm name
     * @return the model and view
     * @throws ActivityException the activity exception
     */
    @Override
    public ModelAndView indexRecord(String vmName, HttpServletRequest request) throws ActivityException {
        //海外标识
        Integer overseas = 0;
        //页面title
        String title = "我的奖品";
        Optional<MediaAppDto> optional = appService.getMediaApp(RequestLocal.get().getAppId());
        if(optional.isPresent()) {
            overseas = optional.get().getOverseas();
        }
        if (null == overseas || 0 == overseas) {
            if (Constants.VALUENAME.DETAIL.equals(vmName)) {
                title = "详情";
            }
        } else if (1 == overseas) {
            if (Constants.VALUENAME.LIST.equals(vmName) || Constants.VALUENAME.OVERDUE.equals(vmName)) {
                title = "My prizes";
            } else {
                title = "Details";
            }
        }
        return new ModelAndView("record/" + vmName)
                .addObject("host", DomainUtil.getHost(request))
                .addObject(Constants.VALUENAME.CONSUMER_ID, RequestLocal.get().getCid())
                .addObject("appId", RequestLocal.get().getAppId())
                .addObject("pageHost", "//" + request.getHeader("host"))
                .addObject(Constants.VALUENAME.OVERSEAS, overseas)
                .addObject(Constants.VALUENAME.TITLE, title);
    }

    /**
     * Click log.
     *
     * @param req the req
     * @throws ActivityException the activity exception
     */
    @Override
    public void clickLog(SpmlogReq req) throws ActivityException {
        // showLogReq.setActivityUseType活动使用类型，0：普通活动，1：兑吧商业化活动 2：推啊商业活动
        /** 增加字段 */
        Long directpage = directPageSourceService.get(RequestLocal.get().getCid());
        if(directpage!=null){
            if(req.getLogExtMap()==null){
                req.setLogExtMap(Maps.newHashMap());
            }
            req.getLogExtMap().put("directpage",String.valueOf(directpage));
        }
        iSpmService.clickLog(req);
    }

    /**
     * Show log.
     *
     * @param req the req
     * @throws ActivityException the activity exception
     */
    @Override
    public void showLog(SpmlogReq req) throws ActivityException {
        // activityUseType活动使用类型，0：普通活动，1：兑吧商业化活动 2：推啊商业活动
        Long directpage = directPageSourceService.get(RequestLocal.get().getCid());
        if(directpage!=null){
            if(req.getLogExtMap()==null){
                req.setLogExtMap(Maps.newHashMap());
            }
            req.getLogExtMap().put("directpage",String.valueOf(directpage));
        }
        iSpmService.showLog(req);
    }

    /**
     * Builds the button URL.
     *
     * @param queryAdvertRsp the query advert rsp
     * @param recordDetail the record detail
     * @throws ActivityException the activity exception
     */
    private void buildButtonUrl(HttpServletRequest request, QueryAdvertRsp queryAdvertRsp, RecordDetailVO recordDetail)
            throws ActivityException {
        Long appId = RequestLocal.get().getAppId();
        Long consumerId = RequestLocal.get().getCid();


        // 7.替换推啊域名
        String promoteUrl = this.replaceLandDomain(queryAdvertRsp.getPromoteUrl(), appId);
        promoteUrl = EmbedUtil.getEncryptUrl(promoteUrl, consumerId);
        String orderId = recordDetail.getOrderId();

        String dpm = DpmInfo.getDpmInfo(appId, Constants.DPM.DPM_B_4, Constants.DPM.DPM_C_1,
                Constants.DPM.DPM_D_0);
        String dcm = DpmInfo.getDcmInfo(queryAdvertRsp.getAdvertId(), queryAdvertRsp.getMaterialId());

        // 5. 跳转url组装并urlEncode
        try {
            promoteUrl = URLEncoder.encode(promoteUrl, "utf-8");
        } catch (UnsupportedEncodingException e) {

            throw new ActivityException(e);

        }

        // 6.需要隐藏特殊网址
        Boolean showUse = true;

        // 6.1如果推广网址不为空或为微信券， 则不展示
        if (((queryAdvertRsp.getCouponType() == 2 || queryAdvertRsp.getCouponType() == 3) && queryAdvertRsp.getIsWeixin() == 1)
                || StringUtils.isBlank(promoteUrl)) {
            showUse = false;
        }

        if (showUse) {
            // 7.跳转web中间页
            promoteUrl = PathUtil.getButtonUrl("//" + request.getHeader("host"), promoteUrl, orderId, dcm, dpm, recordDetail.getActivityId(), CouponSource.ACTIVITY.getCode(), null);

            recordDetail.setIosDownloadUrl(promoteUrl);
            recordDetail.setAndroidDownloadUrl(promoteUrl);
        }
        recordDetail.setShowUse(showUse);
    }


    /**
     * 落地页去除tuia的域名
     *
     * @param promoteUrl
     * @return
     */

    private String replaceLandDomain(String promoteUrl, Long appId) {
        //1.如果不包含.tuia.cn 直接返回
        if (StringUtils.isEmpty(promoteUrl)) {
            return promoteUrl;
        }

        if(promoteUrl.contains(Constants.CUSTOM.TUIA_DOMAIN) || promoteUrl.contains(Constants.CUSTOM.TUIBAT_DOMAIN)) {
            String landUrl = activityService.getLandUrlByAppId(appId);
            if (landUrl != null) {
                if(promoteUrl.contains(Constants.CUSTOM.TUIA_DOMAIN)){
                    promoteUrl = promoteUrl.replace(Constants.CUSTOM.TUIA_DOMAIN, landUrl);
                }else{
                    promoteUrl = promoteUrl.replace(Constants.CUSTOM.TUIBAT_DOMAIN, landUrl);
                }
                promoteUrl = promoteUrl.replace(Constants.VALUENAME.HTTPS_COLON, "").replace(Constants.VALUENAME.HTTP_COLON, "");
            }
        }

        return promoteUrl;
    }

    /**
     * Tuia log process.
     *
     * @param req the req
     * @param request the request
     * @throws ActivityException the activity exception
     */
    @Override
    public void tuiaLogProcess(WebShowClickLogReq req, HttpServletRequest request) throws ActivityException {
        if (StringUtils.isNotBlank(request.getParameter(Constants.DEVICE_TYPE))
                && "tuia".equals(request.getParameter(Constants.DEVICE_TYPE))) {
            if (StringUtils.isNotBlank(RequestLocal.get().getSlotId())) {
                req.setSlotId(Long.valueOf(RequestLocal.get().getSlotId()));
            }
            req.setIp(RequestTool.getIpAddr(request));
            req.setOs(RequestTool.getOSNew(request));
            String agent = RequestTool.getUserAgent(request);
            if (StringUtils.isNotBlank(agent)) {
                req.setUserAgent(agent.length() > 255 ? agent.substring(0, 255) : agent);
            }
            req.setActivityUseType(2);
        }
    }

    /**
     * Tuia direct process.
     *
     * @param req the req
     * @param request the request
     * @throws ActivityException the activity exception
     */
    @Override
    public void tuiaDirectProcess(WebShowClickLogReq req, HttpServletRequest request) throws ActivityException {
        if (StringUtils.isNotBlank(request.getParameter(Constants.DEVICE_TYPE))
                && "tuia".equals(request.getParameter(Constants.DEVICE_TYPE))) {
            if (StringUtils.isNotBlank(RequestLocal.get().getSlotId())) {
                req.setSlotId(Long.valueOf(RequestLocal.get().getSlotId()));
            }
            String dcm = request.getParameter("dcm");
            req.setAdvertId(Long.valueOf(DpmInfo.getParamFromDcm(dcm, 2)));
            req.setIp(RequestTool.getIpAddr(request));
            req.setOs(RequestTool.getOSNew(request));
            String agent = RequestTool.getUserAgent(request);
            if (StringUtils.isNotBlank(agent)) {
                req.setUserAgent(agent.length() > 255 ? agent.substring(0, 255) : agent);
            }
            req.setMaterialId(Long.valueOf(DpmInfo.getParamFromDcm(dcm, 4)));
            req.setUrl(request.getRequestURL().toString());
            req.setAppId(null != RequestLocal.get().getAppId() ? RequestLocal.get().getAppId() : null);
            req.setConsumerId(null != RequestLocal.get().getCid() ? RequestLocal.get().getCid() : null);
            req.setActivityUseType(2);
        }
    }

    /**
     * Url filter.
     *
     * @param url the URL
     * @param orderId the order id
     * @return the string
     * @throws ActivityException the activity exception
     */
    @Override
    public String urlFilter(HttpServletRequest request, String url, String orderId, String consumerId) throws ActivityException {

        String urlNew = url;
        if (!url.startsWith(Constants.PATH.ACTIVITY) && !url.startsWith(Constants.VALUENAME.HTTP_COLON) && !url.startsWith(Constants.VALUENAME.HTTPS_COLON)) {
            if (!urlNew.startsWith("//")) {
                urlNew = "//" + urlNew;
            }
            //获取refer
            String referer = request.getHeader("Referer");
            if (StringUtils.isNotEmpty(referer)) {
                if (referer.startsWith("https")) {
                    urlNew = Constants.VALUENAME.HTTPS_COLON + urlNew;
                } else if (referer.startsWith("http")) {
                    urlNew = Constants.VALUENAME.HTTP_COLON + urlNew;
                }
            }
        }

        // 更新活动中心的微贷网，点击次数，控制消耗。临时需求，后期删除   －－cdm  －－ 2017-07-31
        String location = request.getParameter("location");
        if (null != location && "weidai".equals(location)) {
            activityService.updateAdvertTimes(location);
        }

        urlNew = buildUnApkUrl(urlNew, orderId, consumerId);


        return urlNew;
    }

    private String buildUnApkUrl(String url, String orderId, String consumerId) throws ActivityException {
        String urlNew = url;
        // 如果是大众点评链接，则加上定制后缀
        String param = "&timestamp=" + new Date().getTime() / 1000 + "&request_Id=" + UUID.randomUUID().toString();
        if (urlNew.contains(Constants.CUSTOM.M_DA_DIANPING)) {
            try {
                urlNew = urlNew + URLEncoder.encode(param, "utf-8");
            } catch (Exception e) {
                logger.info(ErrorCode.E0000003.geteCode(), e);
                throw new ActivityException(ErrorCode.E0000003.geteCode(), e.getMessage());

            }
        } else if (urlNew.contains(Constants.CUSTOM.H5_DA_DIANPING)) {
            urlNew = urlNew + param;
        }


        if (!urlNew.endsWith(".apk")) {
            Map<String, String> params = Maps.newHashMap();
            params.put(Constants.THE_TUIA_ID, orderId);
            params.put(Constants.THE_ORDER_ID, orderId);
            params.put(Constants.THE_CONSUMER_ID, consumerId);
            // 如果是奇货域名，增加a_appid参数传递
            if (urlNew.contains(Constants.CUSTOM.QHUO_DOMAIN)) {
                params.put(Constants.THE_APP_ID, RequestLocal.get().getAppId() == null ? null : Long.toString(RequestLocal.get().getAppId()));
            }
            urlNew = UrlUtils.appendParams(urlNew, params);
        }
        return urlNew;
    }


    /**
     * Budil spmlog req.
     *
     * @param req the req
     * @param request the request
     * @return the spmlog req
     * @throws ActivityException the activity exception
     */
    @Override
    public SpmlogReq budilSpmlogReq(WebShowClickLogReq req, HttpServletRequest request) throws ActivityException {

        // 1.兑吧采用传参形式，推啊直接读取cookie。
        bulidSpmlogParam(req, request);

        // 2.copy WebShowClickLogReq to SpmlogReq
        SpmlogReq spmlog = BeanUtils.copy(req, SpmlogReq.class);

        //device_type  判断是否是duiba传入的广告点击
        String deviceType = request.getParameter(Constants.DEVICE_TYPE) ;

        // 3.构建全链路日志监控 log扩展map
        if (StringUtils.isNotBlank(deviceType) && ("duiba".equals(deviceType) || "directad".equals(deviceType))) {
            Enumeration<String> enums = request.getParameterNames();
            Map<String, String> maps = Maps.newHashMap();
            while (enums.hasMoreElements()) {
                String next = enums.nextElement();
                if (next.startsWith("_coll")) {
                    maps.put(next, request.getParameter(next));
                }
            }
            spmlog.setLogExtMap(maps);
        } else {
            spmlog.setLogExtMap(RequestLocal.get().getCollParams());
            spmlog.getLogExtMap().put("use_host", request.getHeader("host"));

            // 3.1.保存cookie中的活动页来源
            EmbedUtil.getSourceMap(request, spmlog.getLogExtMap(), req.getCouponSource(), String.valueOf(req.getActivityId()));
            // 3.2 保存新旧弹层
            EmbedUtil.getLayerMap(DpmInfo.getParamFromDcm(req.getDpm(), 4), spmlog.getLogExtMap());
        }

        return spmlog;
    }

    /**
     * 构件曝光日志参数
     *
     * @param req
     * @param request
     */
    private void bulidSpmlogParam(WebShowClickLogReq req, HttpServletRequest request) {

        if (StringUtils.isNotBlank(request.getParameter(Constants.DEVICE_TYPE))
                && "tuia".equals(request.getParameter(Constants.DEVICE_TYPE))) {
            if (StringUtils.isNotBlank(RequestLocal.get().getSlotId())) {
                req.setSlotId(Long.valueOf(RequestLocal.get().getSlotId()));
            }
            String dcm = request.getParameter("dcm");
            req.setAdvertId(Long.valueOf(DpmInfo.getParamFromDcm(dcm, 2)));
            req.setMaterialId(Long.valueOf(DpmInfo.getParamFromDcm(dcm, 4)));

            req.setIp(RequestTool.getIpAddr(request));
            req.setOs(RequestTool.getOSNew(request));
            String agent = RequestTool.getUserAgent(request);
            if (StringUtils.isNotBlank(agent)) {
                req.setUserAgent(agent.length() > 255 ? agent.substring(0, 255) : agent);
            }
            req.setUrl(request.getRequestURL().toString());
            req.setAppId(null != RequestLocal.get().getAppId() ? RequestLocal.get().getAppId() : null);
            req.setConsumerId(null != RequestLocal.get().getCid() ? RequestLocal.get().getCid() : null);
            req.setActivityUseType(2);
        }

    }

    /**
     * 根据配置比率计算跳转页面类型.
     *
     * @return the int
     */
    private PageType calDestPageType(ProbDto prob, boolean custom) {
        if (custom) {
            return PageType.MAINMEET;
        }
        if (!prob.isSuitable(null)) {
            return PageType.ACTCENTER;
        }

        Map<PageType, Integer> pageRates = new EnumMap<>(PageType.class);
        pageRates.put(PageType.ACTCENTER, prob.getActCenter().intPercentValue());
        pageRates.put(PageType.MAINMEET, prob.getMainMeet().intPercentValue());
        pageRates.put(PageType.URL, prob.getUrl().intPercentValue());
        pageRates.put(PageType.DIRECT, prob.getDirectPage() == null ? 0 : prob.getDirectPage().intPercentValue());
        pageRates.put(PageType.ACTIVITY, prob.getActivity() == null ? 0 : prob.getActivity().intPercentValue());

        // 随机数(0.0000000000000000 到100.0000000000000000)之间的随机数
        double randomNumber = Math.random() * 100;

        double temp = 0.0;
        // 循环遍历得到最终的页面类型
        for (Map.Entry<PageType, Integer> entry : pageRates.entrySet()) {
            temp += Double.valueOf(entry.getValue());
            if (randomNumber <= temp) {
                return entry.getKey();
            }
        }

        // 添加容错机制 如果失败，则选择跳转活动中心
        return PageType.ACTCENTER;
    }

    private Long getDestPageId(PageType type, ProbDto prob, Long slotId, boolean custom) throws ActivityException {

        PageType pageType = type;
        Long pageId = null;
        if (custom) {
            return TempFunction.CUSTOM_PAGE_ID;
        }
        for (int i = 0; i < 3; i++) {
            if (PageType.MAINMEET.equals(pageType)) {

                filterGuidePage(prob, slotId);
                // 跳转到最新的在投主会场
                pageId = guidePageService.getGuidePageId(RequestLocal.get().getAppId(), prob, PageType.MAINMEET);
                if (null != pageId) {
                    return pageId;
                }
                pageType = PageType.ACTCENTER;

            } else if (PageType.ACTCENTER.equals(pageType)) {
                // 跳转到唯一的活动中心
                pageId = guidePageService.getActCenterId();
                if (null != pageId) {
                    return pageId;
                }
                pageType = PageType.DIRECT;
            } else if (PageType.DIRECT.equals(pageType)) {
                // 跳转到 直投页
                pageId = guidePageService.getGuidePageId(RequestLocal.get().getAppId(), prob, PageType.DIRECT);
                if (null != pageId) {
                    return pageId;
                }
                pageType = PageType.MAINMEET;
            }
        }
        return pageId;
    }


    @Override
    public Boolean updateReturnTimes(Long slotId, HttpServletRequest request) throws ActivityException {
        Long consumerId = RequestLocal.get().getCid();
        activityService.updateReturnTimes(slotId, consumerId);
        return true;
    }

    @Override
    public UrlRsp getReturnPage(IndexReq req) throws ActivityException, UnsupportedEncodingException {
        UrlRsp rsp = new UrlRsp();
        // 当不需要返回时候，url置为null
        rsp.setUrl(null);
        Long consumerId = RequestLocal.get().getCid();
        Long appId = RequestLocal.get().getAppId();
        if (isReturnIntercept(consumerId, req.getSlotId(), req.getIp())) {
            // 1.拼接dpm
            String dpm = DpmInfo.getDpmInfo(appId, Constants.DPM.DPM_B_22, 0, 0);
            req.setDpm(dpm);

            // 2.计算跳转页面类型
            ProbDto prob = activityService.selectProb(EntranceType.BACK.getType());
            PageType pageType = calDestPageType(prob, false);

            Integer referPageType = this.getPageTypeFromReferer(req.getReferer());

            //3.拼接dsm dsm_c,dsm_d 在之后会拼接上
            String dsm = DsmInfo.dsmInfo(Constants.DSM.DSM_A_4, Constants.DSM.DSM_B_0,
                    PathUtil.pageTypeToDSMc(referPageType), req.getId());
            req.setDsm(dsm);

            if (PageType.URL.equalsCode(pageType.getCode())) {
                String url = calDestUrl(prob.getUrlList());
                if (StringUtils.isBlank(url)) {
                    return rsp;
                }
                rsp.setUrl(PathUtil.getRedirctUrl(req.getHost(), url, dsm));
            } else {

                // 3.根据跳转页面类型获取可用的流量引导页ID,可能会修改pageType为降级类型
                Long destId = getDestPageId(pageType, prob, req.getSlotId(), false);
                if (null == destId) {
                    return rsp;
                }
                GuidePageDto guidePage = guidePageService.getGuidePage(destId);
                if (guidePage.getPageType() == PageType.DIRECT.getCode()) {
                    String dcm = DpmInfo.dcmInfo(Constants.DCM.DCM_A_1002, Constants.DCM.DCM_DEFAULT, 0, 0L);
                    req.setDcm(dcm);
                }

                rsp.setUrl(PathUtil.getGuidePageUrl(destId, req, guidePage.getPageType()));
            }
        }
        //设置tenter
        String url = rsp.getUrl();
        rsp.setUrl(StringUtils.isNotBlank(url)?
                UrlUtils.appendParams(url, ImmutableMap.of(Constants.TENTER,Tenter.SRP.getCode())):
                url);
        return rsp;
    }

    private String calDestUrl(List<RateDto> list) {
        Map<String, Integer> rates = new HashMap<>();
        int totalRate = 0;
        for (RateDto dto : list) {
            rates.put(dto.getUrl(), dto.getRate());
            totalRate += dto.getRate();
        }

        if (MapUtils.isEmpty(rates)) {
            return null;
        }
        // map 遍历优化
        double randomNumber = Math.random() * totalRate;
        double temp = 0.0;
        //计算随机主会场ID
        for (Map.Entry<String, Integer> entry : rates.entrySet()) {
            temp += Double.valueOf(entry.getValue());
            if (randomNumber <= temp) {
                return entry.getKey();
            }
        }
        return null;
    }

    /**
     * 从referer中的链接 判断当前页面的页面类型
     *
     * @param referer
     * @return pageType
     */
    private Integer getPageTypeFromReferer(String referer) {
        if (StringUtils.isNotBlank(referer)) {
            if (referer.contains(Constants.PATH.MAINMEET + "/")) {
                return PageType.MAINMEET.getCode();
            } else if (referer.contains(Constants.PATH.ACTCENTER + "/")) {
                return PageType.ACTCENTER.getCode();
            } else if (referer.contains(Constants.PATH.ACTIVITY + "/")) {
                return PageType.ACTIVITY.getCode();
            } else {
                if (referer.contains(Constants.PATH.DIRECTPAGE + "/")) {
                    return PageType.DIRECT.getCode();
                }
            }
        }
        return null;
    }

    /**
     * 是否需要拦截返回.
     *
     * @param consumerId the consumer id
     * @param slotId     the slot id
     * @return the string
     * @throws ActivityException the activity exception
     */
    private Boolean isReturnIntercept(Long consumerId, Long slotId, String ip) throws ActivityException {
        int returnTimes = activityService.getReturnTimes(slotId, consumerId);
        Optional<SlotDto> optional = slotService.getSlot(slotId);
        if (optional.isPresent()) {
            SlotDto slotDto = optional.get();
            return Boolean.TRUE.equals(slotDto.getIsReturn()) && returnTimes < slotDto.getNumReturn() && slotService.ipFilter(slotDto, ip, Scene.RETURN);
        }
        return false;
    }

    /**
     * 获取推荐福利位
     *
     * @param req
     * @param request
     * @return
     * @throws ActivityException
     */
    @Override
    public RecommendRsp getRecommend(RecommendReq req, HttpServletRequest request) throws ActivityException {
        RecommendRsp rsp = new RecommendRsp();
        Long appId = RequestLocal.get().getAppId();
        Long consumerId = RequestLocal.get().getCid();
        Integer recommendType = req.getRecommendType();
        if (null == req.getSlotId()) {
            throw new ActivityException(ErrorCode.E0000001);
        }
        if (req.getAppKey() == null) {
            req.setAppKey(remoteMediaService.getMediaApp(appId).getResult().getAppKey());
        }
        // 1.关闭按钮1曝光点击
        BtnClose btnClose = new BtnClose();
        String closeDpm = DpmBuilder.recommendBuild(appId, req.getId(), 4);
        RecommendEmbed recommendEmbed = new RecommendEmbed(null, null, closeDpm, consumerId, appId, req.getHost());
        btnClose.setStInfoClick(recommendEmbed.btnClickInfo());
        btnClose.setStInfoExposure(recommendEmbed.btnExposureInfo());
        rsp.setBtnClose(btnClose);

        if (null != req.getLayerId()) {
            String dsm = DsmInfo.dsmInfo(Constants.DSM.DSM_A_3, req.getLayerId().intValue(), Constants.DSM.DSM_C_1, req.getId());
            req.setDsm(dsm);
        }
        Long directPage = this.directPageSourceService.get(RequestLocal.get().getCid());

        // 2.分别拼接区块1和区块2的dpm
        String dpm1 = null;
        String dcm = null;
        String dpm2 = null;

        int dcmC = 0;
        switch (recommendType) {
            case 1: {//普通推荐位
                dpm1 = DpmInfo.getDpmInfo(appId, Constants.DPM.DPM_B_36, Constants.DPM.DPM_C_1,
                        req.getId().intValue());
                dpm2 = DpmInfo.getDpmInfo(appId, Constants.DPM.DPM_B_36, Constants.DPM.DPM_C_2,
                        req.getId().intValue());
                break;
            }
            case 2: {//支付宝推荐弹层
                dpm1 = DpmInfo.getDpmInfo(appId, Constants.DPM.DPM_B_46, Constants.DPM.DPM_C_3,
                        Constants.DPM.DPM_D_4);
                dpm2 = DpmInfo.getDpmInfo(appId, Constants.DPM.DPM_B_46, Constants.DPM.DPM_C_3,
                        Constants.DPM.DPM_D_5);
                break;
            }
            case 3: {//实物推荐弹层
                dpm1 = DpmInfo.getDpmInfo(appId, Constants.DPM.DPM_B_109, Constants.DPM.DPM_C_2,
                        Constants.DPM.DPM_D_2);
                dpm2 = DpmInfo.getDpmInfo(appId, Constants.DPM.DPM_B_109, Constants.DPM.DPM_C_2,
                        Constants.DPM.DPM_D_3);
                break;
            }
            case 4: {//虚拟奖品弹层
                dpm1 = DpmInfo.getDpmInfo(appId, Constants.DPM.DPM_B_111, Constants.DPM.DPM_C_2,
                        Constants.DPM.DPM_D_2);
                dpm2 = DpmInfo.getDpmInfo(appId, Constants.DPM.DPM_B_111, Constants.DPM.DPM_C_2,
                        Constants.DPM.DPM_D_3);
                dcmC = 5;
                break;
            }
            case 5: {//qb奖品
                dpm1 = DpmInfo.getDpmInfo(appId, Constants.DPM.DPM_B_112, Constants.DPM.DPM_C_3,
                        Constants.DPM.DPM_D_4);
                dpm2 = DpmInfo.getDpmInfo(appId, Constants.DPM.DPM_B_112, Constants.DPM.DPM_C_3,
                        Constants.DPM.DPM_D_5);
                dcmC = 6;
                break;

            }
            case 6: {// 话费奖品
                dpm1 = DpmInfo.getDpmInfo(appId, Constants.DPM.DPM_B_114, Constants.DPM.DPM_C_3,
                        Constants.DPM.DPM_D_4);
                dpm2 = DpmInfo.getDpmInfo(appId, Constants.DPM.DPM_B_114, Constants.DPM.DPM_C_3,
                        Constants.DPM.DPM_D_5);
                break;
            }
            default: {
                // 默认普通推荐位
                dpm1 = DpmInfo.getDpmInfo(appId, Constants.DPM.DPM_B_36, Constants.DPM.DPM_C_1,
                        req.getId().intValue());
                dpm2 = DpmInfo.getDpmInfo(appId, Constants.DPM.DPM_B_36, Constants.DPM.DPM_C_2,
                        req.getId().intValue());
            }
        }
        // 3.整体曝光埋点
        String stRecommendInfo = DpmInfo.setStRecommendInfo(appId, consumerId, DpmBuilder.recommendBuild(appId, req.getId(), 0), null,directPage);
        // 3.3整体曝光埋点
        rsp.setStRecommendInfo(stRecommendInfo);

        ProbDto probDto = filterGuidePageByTag(req.getSlotId(), EntranceType.PRIZERECOMMEDN);
        PageType pageType = calDestPageType(probDto, false);
        Long welfareActivityId = null;
        Long welfareMainMeetId = null;

        // 4.1先得到能出的活动
        List<RateDto> availableActRateDtoList = Lists.newArrayList();
        if (PageType.ACTIVITY.equals(pageType) && !CollectionUtils.isEmpty(probDto.getActivityList())) {
            List<Long> tmpIdList = probDto.getActivityList().stream().map(RateDto::getId).collect(Collectors.toList());
            List<Long> availableActIdListTmp = activityEngineService.getCanUseActIds(tmpIdList, req.getSlotId());
            List<TuiaActivityDto> availableActList = filterTuiaActivityDtoList(req, recommendType != 1, consumerId, availableActIdListTmp);
            if (!CollectionUtils.isEmpty(availableActList)) {
                probDto.getActivityList().forEach(e -> {
                    if (availableActList.stream().anyMatch(x -> x.getId().equals(e.getId()))) {
                        availableActRateDtoList.add(e);
                    }
                });
            }
        }
        if (PageType.ACTIVITY.equals(pageType) && !CollectionUtils.isEmpty(availableActRateDtoList)) {
            //4.2概率落到活动，并且有可出活动的时候
            welfareActivityId = ProbDto.calRate(availableActRateDtoList, null).getId();
        } else {
            //4.3如果不满足4.2条件，走主会场逻辑
            welfareMainMeetId = guidePageService.getGuidePageId(RequestLocal.get().getAppId(), probDto, PageType.MAINMEET);
        }

        // 5.1 构建推荐位block
        buildRecommendBlock(req, rsp, appId, consumerId, recommendType, dpm1, dpm2, dcmC, welfareActivityId, directPage);

        recommendEmbed.setDirectpage(directPage);

        // 5.2 构建福利位block
        buildWelfareBlock(req, rsp, appId, recommendType, recommendEmbed, welfareActivityId, welfareMainMeetId);

        // 4 图片域名切换
        rsp.replaceDomain(DomainUtil.getCurrentYunDomain(request));
        AccessLogFilter.putExPair("dpm", dpm1);
        return rsp;
    }

    /**
     * 构建推荐位区块
     *
     * @throws ActivityException
     */
    private void buildRecommendBlock(RecommendReq req, RecommendRsp rsp, Long appId, Long consumerId, Integer recommendType, String dpm1, String dpm2, int dcmC, Long welfareActivityId, Long directPage) throws ActivityException {
        String dcm;
        List<TuiaActivityDto> nowActs = getTuiaActivityDtos(req, recommendType != 1, consumerId);
        final List<TuiaActivityDto> nowActList = Lists.newArrayList();
        if (!nowActs.isEmpty()) {
            // 去重标题
            nowActs = nowActs.stream().filter(distinctByKey(e -> e.getTitle().replaceAll("[^\u4e00-\u9fa5]", ""))).collect(Collectors.toList());
            if (welfareActivityId != null) {
                final Long welfareActivityIdTmp = welfareActivityId;
                nowActs = nowActs.stream().filter(e -> !e.getId().equals(welfareActivityIdTmp)).collect(Collectors.toList());
            }
            if (!nowActs.isEmpty()) {
                // 随机洗牌
                Collections.shuffle(nowActs);
                // 构造区块
                BlockDto block1 = new BlockDto();
                TuiaActivityDto activity1 = nowActs.get(0);
                nowActList.add(activity1);
                block1.setTitle(activity1.getTitle());
                dcm = DpmInfo.dcmInfo(Constants.DCM.DCM_A_701, activity1.getId(), dcmC, req.getId());
                req.setDcm(dcm);
                req.setDpm(dpm1);
                block1.setActUrl(PathUtil.addParam(
                        PathUtil.getActivityUrl(activity1.getId(), req, null, null),
                        Constants.TENTER,Tenter.SNR.getCode()));
                block1.setBannerUrl(activity1.getBannerUrl());
                block1.setStInfoExposure(DpmInfo.setStRecommendInfo(appId, consumerId, dpm1, dcm, directPage));
                rsp.setBlock1(block1);
                //3.3 在备选的活动列表中选择活动名称中文字符不一致的活动，没有不出

                BlockDto block2 = buildRecommendBlock2(req, appId, consumerId, dpm2, dcmC, directPage, nowActs, nowActList);
                rsp.setBlock2(block2);
            }
        }
    }

    /**
     * 构建推荐弹出的第二个区块
     */
    private BlockDto buildRecommendBlock2(RecommendReq req,
                                          Long appId, Long consumerId, String dpm2, int dcmC, Long directPage, List<TuiaActivityDto> nowActs, List<TuiaActivityDto> nowActList) throws ActivityException {

        /**
         * 定制需求，为唯品会刷量
         */
        String wphReommendConfig = systemConfigService.getSystemConfig("tuia_wph_tmp_recommend_demand");//需要进行配置进行设置开关
        if (TempFunction.isWPHTmpDemandApp(appId, wphReommendConfig, false)) {
            BlockDto block2 = new BlockDto();
            block2.setTitle("唯品会广告");
            StringBuilder url = new StringBuilder();
            url.append("//" + req.getHost());
            url.append("/customized/wphRedirect?");
            try {
                url.append("url=");
                url.append(URLEncoder.encode(TempFunction.WPH_RECOMMEND_URL, "utf-8"));
            } catch (UnsupportedEncodingException e) {
                throw new ActivityException(e);
            }

            String dcm = DpmInfo.dcmInfo(Constants.DCM.DCM_A_112, (long) Constants.DCM.DCM_B_0, Constants.DCM.DCM_C_0, req.getId());

            if (LoginType.NORMAL.equalsCode(req.getLogin())) {
                url.append(Constants.PARAM.SLOTID).append(req.getSlotId());
                url.append(Constants.PARAM.DEVICEID).append(req.getDeviceId());
            }
            url.append(Constants.PARAM.LOGIN).append(req.getLogin());
            url.append(Constants.PARAM.APPKEY).append(req.getAppKey());
            url.append(Constants.PARAM.DPM).append(dpm2);
            url.append(Constants.PARAM.DCM).append(dcm);
            if (!StringUtils.isEmpty(req.getDsm())) {
                url.append(Constants.PARAM.DSM).append(req.getDsm());
            }
            block2.setActUrl(url.toString());
            block2.setBannerUrl(TempFunction.WPH_MATERIAL_URL);

            block2.setStInfoExposure(DpmInfo.setStRecommendInfo(appId,consumerId,dpm2,dcm,directPage));
            return block2;
        }

        if (nowActs.size() >= 2) {
            TuiaActivityDto activity2 = nowActs.get(1);
            nowActList.add(activity2);
            BlockDto block2 = new BlockDto();
            block2.setTitle(activity2.getTitle());
            String dcm = DpmInfo.dcmInfo(Constants.DCM.DCM_A_701, activity2.getId(), dcmC, req.getId());
            req.setDcm(dcm);
            req.setDpm(dpm2);
            block2.setActUrl(PathUtil.addParam(
                    PathUtil.getActivityUrl(activity2.getId(), req, null, null),
                    Constants.TENTER,Tenter.SNR.getCode()));
            block2.setBannerUrl(activity2.getBannerUrl());
            block2.setStInfoExposure(DpmInfo.setStRecommendInfo(appId, consumerId, dpm2, dcm, directPage));
            return block2;
        }
        return null;
    }


    /**
     * 构建福利位按钮
     *
     * @param req
     * @param rsp
     * @param appId
     * @param recommendType
     * @param recommendEmbed
     * @param welfareActivityId
     * @param welfareMainMeetId
     */
    private void buildWelfareBlock(RecommendReq req, RecommendRsp rsp, Long appId, Integer recommendType, RecommendEmbed recommendEmbed, Long welfareActivityId, Long welfareMainMeetId) {
        if (recommendType == 1 && (welfareActivityId != null || welfareMainMeetId != null)) {
            //普通弹层推荐列表更多活动按钮埋点
            String dpm3 = DpmInfo.getDpmInfo(appId, Constants.DPM.DPM_B_36, Constants.DPM.DPM_C_3,
                    req.getId().intValue());
            String dpm4 = DpmInfo.getDpmInfo(appId, Constants.DPM.DPM_B_36, Constants.DPM.DPM_C_5,
                    req.getId().intValue());
            String moreDcm = null;
            String block3ActUrl = null;
            String block4ActUrl = null;
            if (welfareActivityId != null) {
                moreDcm = DcmBuilder.recommendBuild(Constants.DCM.DCM_A_701, welfareActivityId);
                block3ActUrl = PathUtil.getActivityUrl(welfareActivityId, req, null, null);
                block4ActUrl = PathUtil.getActivityUrl(welfareActivityId, req, null, null);
            } else {
                moreDcm = DcmBuilder.recommendBuild(Constants.DCM.DCM_A_1015, welfareMainMeetId);
                block3ActUrl = PathUtil.getGuidePageUrlforRecommendPage(welfareMainMeetId, req, PageType.MAINMEET.getCode(), dpm3);
                block4ActUrl = PathUtil.getGuidePageUrlforRecommendPage(welfareMainMeetId, req, PageType.MAINMEET.getCode(), dpm4);
            }
            BlockDto block3 = new BlockDto();
            recommendEmbed.setDpm(dpm3);
            recommendEmbed.setDcm(moreDcm);
            block3.setStInfoExposure(recommendEmbed.btnExposureInfo());
            BlockDto block4 = new BlockDto();
            recommendEmbed.setDpm(dpm4);
            recommendEmbed.setDcm(moreDcm);
            block4.setStInfoExposure(recommendEmbed.btnExposureInfo());
            block3.setActUrl(PathUtil.addParam(block3ActUrl, Constants.TENTER,Tenter.SNR.getCode()));
            block4.setActUrl(PathUtil.addParam(block4ActUrl, Constants.TENTER,Tenter.SNR.getCode()));
            rsp.setBlock3(block3);
            rsp.setBlock4(block4);
        }
    }

    private static <T> Predicate<T> distinctByKey(Function<? super T, Object> keyExtractor) {
        Map<Object, Boolean> seen = new ConcurrentHashMap<>();
        return object -> seen.putIfAbsent(keyExtractor.apply(object), Boolean.TRUE) == null;
    }

    @Override
    public RecommendRsp getCloseRecommend(RecommendReq req, HttpServletRequest request) throws ActivityException {
        RecommendRsp rsp = new RecommendRsp();
        Long appId = RequestLocal.get().getAppId();
        Long consumerId = RequestLocal.get().getCid();
        if (null == req.getSlotId()) {
            throw new ActivityException(ErrorCode.E0000001);
        }
        if (req.getAppKey() == null) {
            req.setAppKey(remoteMediaService.getMediaApp(appId).getResult().getAppKey());
        }
        //关闭按钮1曝光点击
        BtnClose btnClose = new BtnClose();
        String closeDpm = DpmBuilder.recommendBuild(appId, req.getId(), 6);
        RecommendEmbed recommendEmbed = new RecommendEmbed(null, null, closeDpm, consumerId, appId, req.getHost());
        btnClose.setStInfoClick(recommendEmbed.btnClickInfo());
        btnClose.setStInfoExposure(recommendEmbed.btnExposureInfo());
        rsp.setBtnClose(btnClose);

        AccessLogFilter.putExPair("dpm", closeDpm);
        return rsp;
    }

    public TuiaActivityDto filterTitleSame(List<TuiaActivityDto> acts, String tempTitle) {
        String pattern = "[^\u4e00-\u9fa5]";
        String sample = tempTitle.replaceAll(pattern, "");
        for (TuiaActivityDto dto : acts) {
            String title = dto.getTitle();
            title = title.replaceAll(pattern, "");
            if (!sample.equals(title)) {
                return dto;
            }
        }
        return null;
    }

    /**
     * 获取推荐的可出活动列表
     * 过滤逻辑：
     * 1.用户参与次数用完的活动
     * 2.当前活动
     * 3.活动标签命中广告位屏蔽标签
     * @param req 请求参数
     * @param isAlipay 是否奖品弹层(抽奖次数用完后的推荐位，奖品中奖弹层，两者出活动逻辑不同)
     * @param consumerId
     * @return
     * @throws ActivityException
     */
    public List<TuiaActivityDto> getTuiaActivityDtos(IndexReq req, Boolean isAlipay, Long consumerId) throws ActivityException {
        // 1.获取推荐的活动列表
        List<Long> ids;
        if (isAlipay) {
            ids = activityEngineService.getActivityByUVLaunch(req.getSlotId());
        } else {
            ids = activityEngineService.getNewIds(1, req.getSlotId());
        }
        return filterTuiaActivityDtoList(req, isAlipay, consumerId, ids);
    }

    private List<TuiaActivityDto> filterTuiaActivityDtoList(IndexReq req, Boolean isAlipay, Long consumerId, List<Long> ids) throws ActivityException {
        List<TuiaActivityDto> acts = activityService.getBatchActivitys(ids);

        if (CollectionUtils.isEmpty(acts)) {
            return Collections.emptyList();
        }

        List<String> slotTags = this.slotService.getSlotIdTags(req.getSlotId());
        Map<Long, Set<Long>> tags = this.activityService.getActivitysTags(ids);

        // 2.1获取用户当前已经抽完的活动
        Map<Object, Object> notShowIds = activityService.getConsumerActivityDojoinCacheMap(consumerId);

        // 2.2排除当前活动和改用户已经抽完的活动
        List<TuiaActivityDto> nowActs = new ArrayList<>();
        for (TuiaActivityDto dto : acts) {
            if (!dto.getId().equals(req.getId())) {
                Object o = notShowIds.get(String.valueOf(dto.getId()));
                if (!CollectionTool.containsStringAny(tags.get(dto.getId()), slotTags) && (o == null || (!isAlipay && dto.getLimitCount() > Integer.valueOf(o.toString())))) {
                    nowActs.add(dto);
                }

            }
        }
        return nowActs;
    }

    @Override
    public BuoyRsp getBuoy(IndexReq req, HttpServletRequest request) {
        Long appId = RequestLocal.get().getAppId();
        Long consumerId = RequestLocal.get().getCid();
        boolean custom = TempFunction.customBuoy(req.getId(), req.getPageId());

        try {
            BuoyRsp rsp = new BuoyRsp();

            // 1.随机获取浮标样式
            // 1.1.查询并验证活动信息
            TuiaActivityDto activityDto = activityService.getActivityById(req.getId());


            if (!TempFunction.displayBuoy(activityDto.getId())) {
                return null;
            }

            // 2.计算跳转页面类型
            ProbDto prob = activityService.selectProb(EntranceType.BROB.getType());
            PageType pageType = calDestPageType(prob, custom);

            BuoyDto buoy;
            String dpm = null;

            // 临时需求 这些广告位走唯品会落地页
            String wphBuoyDemand = systemConfigService.getSystemConfig("tuia_wph_tmp_buoy_demand");
            if (TempFunction.isWPHTmpDemandApp(RequestLocal.get().getAppId(), wphBuoyDemand, true)) {
                buoy = activityService.selectBuoy(TempFunction.WPH_BUOY_ID);
                if (buoy == null) {
                    return null;
                }
                String dsm = DsmInfo.dsmInfo(Constants.DSM.DSM_A_2, buoy.getId().intValue(), Constants.DSM.DSM_C_1, req.getId());
                dpm = DpmInfo.getDpmInfo(appId, Constants.DPM.DPM_B_21, buoy.getId().intValue(),
                        activityDto.getId().intValue());
                req.setDpm(dpm);
                req.setDsm(dsm);
                rsp.setId(buoy.getId()).setStBuoyInfo(DpmInfo.setStBuoyInfo(appId, consumerId, "//" + request.getHeader("host"), dpm))
                        .setStyleCode(buoy.getStyleCode()).setBuoyDestUrl(PathUtil.getRedirctUrl(request.getHeader("host"), TempFunction.WPH_BUOY_URL, dsm));

            } else {
                GuidePageRspBuilder guidePageRspBuilder = new GuidePageRspBuilder(req, request, appId, consumerId, custom, rsp, activityDto, prob, pageType, dpm).invoke();
                if (guidePageRspBuilder.is())
                    return null;
                buoy = guidePageRspBuilder.getBuoy();
                dpm = guidePageRspBuilder.getDpm();

            }


            // 7. 图片域名切换
            rsp.replaceDomain(DomainUtil.getCurrentYunDomain(request));

            //设置浮标id到统一访问日志
            AccessLogFilter.putExPair("buoyId", buoy.getId().toString());
            if (null != dpm) {
                AccessLogFilter.putExPair("dpm", dpm);
            }
            //设置towId
            rsp.setBuoyDestUrl(PathUtil.addParam(rsp.getBuoyDestUrl(), Constants.TOW_ID, UUID.randomUUID().toString()));
            //设置tenter
            rsp.setBuoyDestUrl(PathUtil.addParam(rsp.getBuoyDestUrl(),Constants.TENTER,Tenter.SBY.getCode()));

            return rsp;

        } catch (Exception e) {
            logger.info("配置浮标失败，参数=[{}]", request, e);
            return null;
        }

    }


    public BuoyDto getUrlBuoy(IndexReq req, HttpServletRequest request, Long appId, Long consumerId, BuoyRsp rsp, TuiaActivityDto activityDto, ProbDto prob) throws ActivityException, UnsupportedEncodingException {
        BuoyDto buoy;

        //计算概率，算出url，浮标id
        RateDto rate = ProbDto.calRate(prob.getUrlList(), null);
        if (rate == null) {
            return null;
        }
        //浮标id
        Long buoyId = rate.getBuoyId();
        //URL
        String url = rate.getUrl();
        buoy = activityService.selectBuoy(buoyId);
        if (null == buoy) {
            return null;
        }
        String dpm = DpmInfo.getDpmInfo(appId, Constants.DPM.DPM_B_21, buoy.getId().intValue(),
                activityDto.getId().intValue());
        String dsm = DsmInfo.dsmInfo(Constants.DSM.DSM_A_2, buoy.getId().intValue(), Constants.DSM.DSM_C_1, req.getId());
        rsp.setStBuoyInfo(DpmInfo.setStBuoyInfo(appId, consumerId, "//" + request.getHeader("host"), dpm));
        rsp.setStyleCode(buoy.getStyleCode());
        if (StringUtils.isBlank(url)) {
            return null;
        }
        rsp.setBuoyDestUrl(PathUtil.getRedirctUrl(request.getHeader("host"), url, dsm));
        return buoy;
    }

    @Override
    public List<LayerSkinDto> getAllLayerSkin(SkinReq req, HttpServletRequest request) {
        try {
            String domain = DomainUtil.getCurrentYunDomain(request);
            List<LayerSkinDto> list = this.skinService.selectAllLayerSkin(req);

            List<LayerSkinDto> rs = BeanUtils.copyList(list, LayerSkinDto.class);
            for (LayerSkinDto dto : rs) {
                dto.setCode(DomainUtil.replaceDomain(dto.getCode(), domain));
                dto.setImage(DomainUtil.replaceDomain(dto.getImage(), domain));
            }
            return rs;
        } catch (Exception e) {
            logger.info("获取弹层皮肤失败,参数=[{}]", JSONObject.toJSONString(req));
            return Lists.newArrayList();
        }

    }

    @Override
    public KefuResponse getKefu(Long slotId, HttpServletRequest request) throws ExecutionException, ActivityException {
        KefuResponse response = new KefuResponse();

        //获取客服按钮样式
        Optional<SlotDto> optional = slotService.getSlot(slotId);
        if (optional.isPresent()) {
            Long buttonId = optional.get().getShowServiceId();
            if (buttonId != null) {
                ButtonDto buttonDto = skinService.getButtonById(buttonId);
                response.setId(buttonId);
                response.setButtonCode(buttonDto.getButtonCode());
                ContactPlateDto contactPlateDto = contactPlateService.getDtoByHost(request.getHeader("host"));
                response.setPhone(contactPlateDto == null ? "" : contactPlateDto.getOnlinePhone());

                //埋点
                Long appId = RequestLocal.get().getAppId();
                Long consumerId = RequestLocal.get().getCid();
                String host = "//" + request.getHeader("host");
                response.setEmbed(KeFuEmbed.buildStEmbed(appId, buttonId, consumerId, host));
                AccessLogFilter.putExPair("dpm", DpmBuilder.kefuBuild(appId));
                AccessLogFilter.putExPair("dcm", DcmBuilder.kefuBuild(buttonId));
            }
        }
        return response;
    }


    @Override
    public List<AlipayWinInfoRsp> getAlipayWinInfo() {
        List<AlipayWinInfoRsp> result = new ArrayList<>();

        //基于媒体维度获取
        Long appId = RequestLocal.get().getAppId();
        if (appId != null) {
            return advancedCacheClient.getWithCacheLoader(CachedKeyUtils.getRedisKey(CacheKey.ALIPAY_WIN_APP_KEY, appId),
                    5, TimeUnit.MINUTES, () -> {
                        List<AlipayOrderDto> alipayOrderDtos = activityOrderService.selectAlipayRecords(initAliOrderQuery(appId, 100));
                        if (CollectionUtils.isNotEmpty(alipayOrderDtos)) {
                            for (AlipayOrderDto dto : alipayOrderDtos) {
                                AlipayWinInfoRsp alipayWinInfoRsp = new AlipayWinInfoRsp();
                                alipayWinInfoRsp.setAccount(buildAccount(dto.getId(), dto.getAliAccount()));
                                alipayWinInfoRsp.setAmount(String.format("%.2f", dto.getAwardAmount() * 1.0 / 100));
                                result.add(alipayWinInfoRsp);
                            }
                        }
                        return result;
                    });
        }
        return result;
    }

    /**
     * 初始化支付宝订单查询参数
     *
     * @param appId appId
     * @return ReqAliOrderQuery
     */
    private ReqAliOrderQuery initAliOrderQuery(Long appId, Integer pageSize) {
        Integer rowStart = 0;
        pageSize = pageSize == null ? 50 : pageSize;
        List<Integer> status = null;
        List<Long> activityIds = null;
        List<Long> appIds = new ArrayList<>();
        appIds.add(appId);
        Long slotId = null;
        Date end = new Date();
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        Date start = calendar.getTime();
        return new ReqAliOrderQuery(rowStart, pageSize, status,
                activityIds, appIds, slotId, start, end);
    }

    /**
     * 支付宝中奖（春雨医生）-构建用户名
     *
     * @return string
     */
    private String buildAccount(Long id, String aliAccount) {
        //生成随机手机号
        if (StringUtils.isEmpty(aliAccount) || aliAccount.length() < 6) {
            return advancedCacheClient.getWithCacheLoader(CachedKeyUtils.getRedisKey(CacheKey.ALIPAY_WIN_ACCOUNT, id),
                    getRestSecondsToday(), TimeUnit.SECONDS, PhoneTool::createPartialNumber);
        }

        StringBuilder sb = new StringBuilder();
        sb.append(aliAccount.substring(0, 3));
        sb.append("****");
        sb.append(aliAccount.substring(aliAccount.length() - 4, aliAccount.length()));
        return sb.toString();
    }

    @Override
    public List<AlipayWinInfoRsp> getRealWinInfo(Long id) {
        List<AlipayWinInfoRsp> result = new ArrayList<>();

        //基于活动维度获取
        if (id != null) {
            return advancedCacheClient.getWithCacheLoader(CachedKeyUtils.getRedisKey(CacheKey.REAL_WIN_ACTIVITY_ID, id),
                    5, TimeUnit.MINUTES, () -> {
                        List<AlipayOrderDto> alipayOrderDtos = activityOrderService.selectAlipayRecords(initRealOrderQuery(id, 100));
                        if (CollectionUtils.isNotEmpty(alipayOrderDtos)) {
                            Map<Long, PrizeDto> map = buildPrizeMap(id);
                            for (AlipayOrderDto dto : alipayOrderDtos) {
                                //封装中奖信息
                                result.add(getWinnerInfoByType(dto, map));
                            }
                        }
                        return result;
                    });
        }
        return result;
    }


    @Override
    public ProbDto filterGuidePageByTag(Long slotId, EntranceType entranceType) throws ActivityException {
        ProbDto probDto = activityService.selectProb(entranceType.getType());
        if (null != probDto){
            PageType pageType = calDestPageType(probDto, false);
            if ((EntranceType.PRIZERECOMMEDN.equals(entranceType)|| pageType.equalsCode(PageType.MAINMEET.getCode()))){
                return filterGuidePage(probDto,slotId);
            }
        }

        return probDto;
    }

    private ProbDto filterGuidePage(ProbDto probDto, Long slotId){
        List<String> slotTag = this.slotService.getSlotIdTags(slotId);
        if (CollectionUtils.isEmpty(slotTag)) {
            return probDto;
        }
        List<RateDto> rateDtos = probDto.getMainMeetList();
        List<RateDto> rsDtos = new ArrayList<>();
        List<Long> ids = EntityUtil.getParam(rateDtos, RateDto::getId);
        //获取流量引导页上活动的标签
        Map<Long, Set<Long>> tagMap = this.guidePageService.getMainMeetActivityTag(ids);
        if (tagMap == null || tagMap.isEmpty()) {
            return probDto;
        }

        //获取配置中得到流量引导页列表并且过滤
        for (RateDto rateDto : rateDtos){
            Set<Long> tags = tagMap.get(rateDto.getId());
           if( null == tags ||!CollectionTool.containsStringAny(tags,slotTag)){
               rsDtos.add(rateDto);
           }
        }
        probDto.setMainMeetList(rsDtos);
        return probDto;
    }

    /**
     * 初始化支付宝订单查询参数
     *
     * @param id
     * @return ReqAliOrderQuery
     */
    private ReqAliOrderQuery initRealOrderQuery(Long id, Integer pageSize) {
        Integer rowStart = 0;
        pageSize = pageSize == null ? 50 : pageSize;
        List<Integer> status = null;
        List<Long> activityIds = new ArrayList<>();
        activityIds.add(id);
        List<Long> appIds = null;
        Long slotId = null;
        return new ReqAliOrderQuery(rowStart, pageSize, status,
                activityIds, appIds, slotId, null, null);
    }

    /**
     * 构建活动下的奖项奖品map<optionId, prizeDto>
     *
     * @param id
     * @return
     */
    private Map<Long, PrizeDto> buildPrizeMap(Long id) {
        List<ActivityOptionDto> optionDtos;
        try {
            optionDtos = activityService.selectActivityOptionsFromCache(id);
            if (CollectionUtils.isNotEmpty(optionDtos)) {
                Map<Long, PrizeDto> map = new HashMap<>();
                //根据奖品id批量获取奖品
                List<Long> prizeIds = new ArrayList<>();
                for(ActivityOptionDto optionDto : optionDtos) {
                    prizeIds.add(optionDto.getPrizeId());
                }
                List<PrizeDto> prizeDtos = prizeService.selectByIds(prizeIds);
                for (ActivityOptionDto optionDto : optionDtos) {
                    for (PrizeDto prizeDto : prizeDtos) {
                        if (prizeDto.getId().equals(optionDto.getPrizeId())) {
                            map.put(optionDto.getId(), prizeDto);
                            break;
                        }
                    }
                }
                return map;
            }
        } catch (Exception e) {
            logger.warn("buildPrizeMap error", e);
            return new HashMap<>();
        }
        return new HashMap<>();
    }

    /**
     * 根据奖品类型返回中奖信息
     *
     * @param dto
     * @return
     */
    private AlipayWinInfoRsp getWinnerInfoByType(AlipayOrderDto dto, Map<Long, PrizeDto> map) {
        AlipayWinInfoRsp alipayWinInfoRsp = new AlipayWinInfoRsp();
        StringBuilder content = new StringBuilder("");
        //支付宝红包
        if (AlipayType.isAli(dto.getAlipayType())) {
            alipayWinInfoRsp.setAccount(buildRealWinnerAccount(dto.getAliAccount(), dto.getStatus()));
            alipayWinInfoRsp.setAmount(String.format("%.2f", dto.getAwardAmount() * 1.0 / 100));
            String valueUnit = Constants.CONSTANT.YUAN;
            alipayWinInfoRsp.setContent(content.append(alipayWinInfoRsp.getAmount()).append(valueUnit).append("支付宝红包").toString());
        }
        //实物
        else if (AlipayType.isPhysical(dto.getAlipayType())) {
            alipayWinInfoRsp.setAccount(buildRealWinnerAccount(dto.getAliAccount(), dto.getStatus()));
            alipayWinInfoRsp.setContent(content.append(dto.getPrizeTitle()).toString());
        }
        //虚拟奖品
        else if (AlipayType.isVirturalOrSubVirtural(dto.getAlipayType())) {
            //数值充值
            if (AlipayType.VIRTUAL_API_1.getType().equals(dto.getAlipayType())) {
                alipayWinInfoRsp.setAccount(buildRealWinnerAccount(getVirtualPhone(dto), dto.getStatus()));
                alipayWinInfoRsp.setAmount(String.format("%.2f", dto.getAwardAmount() * 1.0 / 100));
                String valueUnit = map.get(dto.getPrizeId()) == null ? "" : map.get(dto.getPrizeId()).getApiRechargeDto().getValueUnit();
                alipayWinInfoRsp.setContent(content.append(alipayWinInfoRsp.getAmount()).append(valueUnit).toString());
            } else {
                alipayWinInfoRsp.setAccount(buildRealWinnerAccount(getVirtualPhone(dto), dto.getStatus()));
                alipayWinInfoRsp.setContent(content.append(dto.getPrizeTitle()).toString());
            }
        }
        //Q币
        else if (AlipayType.isQB(dto.getAlipayType())) {
            Integer prizeValue = map.get(dto.getPrizeId()) == null ? 1 : map.get(dto.getPrizeId()).getPrizeValue();
            alipayWinInfoRsp.setAccount(buildRealWinnerAccount(dto.getAliAccount(), dto.getStatus()));
            alipayWinInfoRsp.setAmount(String.valueOf(dto.getAwardAmount() / prizeValue));
            String valueUnit = Constants.CONSTANT.GE;
            alipayWinInfoRsp.setContent(content.append(alipayWinInfoRsp.getAmount()).append(valueUnit).append("Q币").toString());
            //话费
        } else if (AlipayType.isBill(dto.getAlipayType())) {
            alipayWinInfoRsp.setAccount(buildRealWinnerAccount(dto.getAliAccount(), dto.getStatus()));
            alipayWinInfoRsp.setAmount(String.format("%.2f", dto.getAwardAmount() * 1.0 / 100));
            String valueUnit = Constants.CONSTANT.YUAN;
            alipayWinInfoRsp.setContent(content.append(alipayWinInfoRsp.getAmount()).append(valueUnit).append("话费").toString());
        }

        return alipayWinInfoRsp;
    }

    /**
     * 获取虚拟奖品获奖者手机号
     *
     * @param dto
     * @return
     */
    private String getVirtualPhone(AlipayOrderDto dto) {
        if (CollectionUtils.isNotEmpty(dto.getContextArray())) {
            for (VirtualContext virtualContext : dto.getContextArray()) {
                if (AccountRecharge.TYPE_ACCOUNT_PHONE_NUM.getType().equals(virtualContext.getType())) {
                    return virtualContext.getValue();
                }
            }
        }
        return null;
    }

    /**
     * 真实中奖-构建用户名
     *
     * @return string
     */
    private String buildRealWinnerAccount(String account, Integer status) {
        if (StringUtils.isBlank(account) || !AlipayOrderStatus.SUCCESS.getStatus().equals(status)) {
            return Constants.CONSTANT.VISITOR;
        }
        StringBuilder sb = new StringBuilder();
        sb.append(account.substring(0, 3));
        sb.append("****");
        sb.append(account.substring(account.length() - 4, account.length()));
        return sb.toString();
    }

    @Override
    public PublicNoticeRsp publicNotice(Long id, UserAccount consumer, HttpServletRequest request) {
        PublicNoticeRsp response = new PublicNoticeRsp();

        if (StringUtils.isNotBlank(RequestLocal.get().getSlotId())) {
            //根据广告位选择展示中公示样式
            Long slotId  = Long.valueOf(RequestLocal.get().getSlotId());
            Optional<SlotDto> optional = slotService.getSlot(Long.valueOf(slotId));
            if(optional.isPresent() && optional.get().getPlugBuoyConfigDto() != null) {
                Long publicityId = optional.get().getPlugBuoyConfigDto().getPublicityId();
                if (publicityId != null) {
                    PublicNoticeStyleDto dto = publicNoticeStyleService.getById(publicityId);
                    if (dto != null) {
                        response.setId(dto.getId());
                        response.setStyleCode(dto.getStyleCode());
                        //中奖用户信息
                        response.setList(getRealWinInfo(id));
                        response.setEmbedData(ActivityEmbed.buildPublicNoticeEmbed(consumer, request.getHeader("host"), id, publicityId));
                    }
                }
            }
        }

        return response;
    }

    /**
     * 中奖公示预览 测试数据随便写写的
     *
     * @param id
     * @return
     */
    @Override
    public PublicNoticeRsp publicNoticePriviewData(Long id) {
        PublicNoticeRsp response = new PublicNoticeRsp();
        //中奖公示样式信息
        PublicNoticeStyleDto dto = publicNoticeStyleService.getById(id);
        response.setStyleCode(dto.getStyleCode());
        //预览测试数据-用户中奖信息
        List<AlipayWinInfoRsp> list = new ArrayList<>();
        AlipayWinInfoRsp alipayWinInfoRsp = new AlipayWinInfoRsp();
        alipayWinInfoRsp.setAccount("游客");
        alipayWinInfoRsp.setContent("1.11元支付宝红包");
        list.add(alipayWinInfoRsp);
        alipayWinInfoRsp = new AlipayWinInfoRsp();
        alipayWinInfoRsp.setAccount("游客");
        alipayWinInfoRsp.setContent("iphoneX");
        list.add(alipayWinInfoRsp);
        alipayWinInfoRsp = new AlipayWinInfoRsp();
        alipayWinInfoRsp.setAccount("游客");
        alipayWinInfoRsp.setContent("10比特币");
        list.add(alipayWinInfoRsp);
        alipayWinInfoRsp = new AlipayWinInfoRsp();
        alipayWinInfoRsp.setAccount("游客");
        alipayWinInfoRsp.setContent("10个Q币");
        list.add(alipayWinInfoRsp);
        response.setList((list));
        return response;
    }

    @Override
    public PullDownRsp getPullDown(IndexReq req, HttpServletRequest request) throws ActivityException {
        Long appId = RequestLocal.get().getAppId();
        Long consumerId = RequestLocal.get().getCid();
        String host = "//" + req.getHost();
        //设置dsm
        req.setDsm(DsmBuilder.pullDownBuild(req.getId()));
        PullDownRsp rsp = PullDownData.getData(req);
        //跳转页面素材提前加载
        GuidePageDto dto = guidePageService.getGuidePage(rsp.getPageId());
        GuidePageSkinDto skin = guidePageService.getGuidePageSkin(dto.getSkinId());
        rsp.setPageCode(DomainUtil.replaceDomain(skin.getHtml(), DomainUtil.getCurrentYunDomain(request)));
        //埋点信息
        rsp.setEmbed(ActivityEmbed.buildPullDownEmbed(appId, consumerId, host, req.getId()));
        //曝光信息
        AccessLogFilter.putExPair("dpm", DpmBuilder.pullDownExposureBuild(appId));
        AccessLogFilter.putExPair("dcm", DcmBuilder.pullDownBuild(req.getId()));
        //设置tenter
        rsp.setUrl(PathUtil.addParam(rsp.getUrl(),Constants.TENTER,Tenter.SPD.getCode()));

        return rsp;
    }

    private class GuidePageRspBuilder {
        private boolean myResult;
        private IndexReq req;
        private HttpServletRequest request;
        private Long appId;
        private Long consumerId;
        private boolean custom;
        private BuoyRsp rsp;
        private TuiaActivityDto activityDto;
        private ProbDto prob;
        private PageType pageType;
        private String dpm;
        private BuoyDto buoy;

        public GuidePageRspBuilder(IndexReq req, HttpServletRequest request, Long appId, Long consumerId, boolean custom, BuoyRsp rsp, TuiaActivityDto activityDto, ProbDto prob, PageType pageType, String dpm) {
            this.req = req;
            this.request = request;
            this.appId = appId;
            this.consumerId = consumerId;
            this.custom = custom;
            this.rsp = rsp;
            this.activityDto = activityDto;
            this.prob = prob;
            this.pageType = pageType;
            this.dpm = dpm;
        }

        boolean is() {
            return myResult;
        }

        public BuoyDto getBuoy() {
            return buoy;
        }

        public String getDpm() {
            return dpm;
        }

        public GuidePageRspBuilder invoke() throws ActivityException, UnsupportedEncodingException {
            // 临时需求 这些广告位只走固定主会场
            if (TempFunction.isTmpDemandSlot(req.getSlotId())) {
                pageType = PageType.MAINMEET;
            }

            if (PageType.URL.equalsCode(pageType.getCode())) {
                buoy = getUrlBuoy(req, request, appId, consumerId, rsp, activityDto, prob);
                if (buoy == null) {
                    myResult = true;
                    return this;
                }
            } else {
                // 3.根据跳转页面类型获取可用的流量引导页ID,可能会修改pageType为降级类型
                Long destId;
                destId = getDestId(req, custom, prob, pageType);

                if (null == destId) {
                    myResult = true;
                    return this;
                }
                GuidePageDto guidePage = guidePageService.getGuidePage(destId);

                //4.获取浮标
                buoy = getGuidePageBuoy(activityDto.getBuoyId(), guidePage, custom, req);
                if (null == buoy) {
                    myResult = true;
                    return this;
                }
                rsp.setId(buoy.getId());
                // 5.拼接dpm
                dpm = DpmInfo.getDpmInfo(appId, Constants.DPM.DPM_B_21, buoy.getId().intValue(),
                        activityDto.getId().intValue());
                req.setDpm(dpm);

                //6.拼接dsm_c,dsm_d pageId在之后会添加  因为浮标只会在活动出现所以目前写死1
                String dsm = DsmInfo.dsmInfo(Constants.DSM.DSM_A_2, buoy.getId().intValue(), Constants.DSM.DSM_C_1, req.getId());
                req.setDsm(dsm);

                rsp.setStBuoyInfo(DpmInfo.setStBuoyInfo(appId, consumerId, "//" + request.getHeader("host"), dpm));
                rsp.setStyleCode(buoy.getStyleCode());

                if (guidePage.getPageType().equals(PageType.DIRECT.getCode())) {
                    String dcm = DpmInfo.dcmInfo(Constants.DCM.DCM_A_1002, Constants.DCM.DCM_DEFAULT, 0, 0L);
                    req.setDcm(dcm);
                }
                rsp.setBuoyDestUrl(PathUtil.getGuidePageUrl(destId, req, guidePage.getPageType()));
            }
            myResult = false;
            return this;
        }

        /**
         * 得到浮标跳转页面ID
         *
         * @param req
         * @param custom
         * @param prob
         * @param pageType
         * @return
         * @throws ActivityException
         */
        private Long getDestId(IndexReq req, boolean custom, ProbDto prob, PageType pageType) throws ActivityException {
            Long destId;
            if (TempFunction.isTmpDemandSlot(req.getSlotId())) {
                //临时需求，固定广告位出固定主会场
                destId = TempFunction.getTmpDemandMainMeetId();
            } else {
                destId = getDestPageId(pageType, prob, req.getSlotId(), custom);
            }
            return destId;
        }

        /***
         * @Description: getGuidePageBuoy 确定浮标跳转的浮标样式
         *
         * @Param: [pageId]
         * @Return: cn.com.duiba.tuia.activity.center.api.dto.BuoyDto
         * @throws:
         * @author: youhaijun
         * @Date: 2017/8/15
         */
        private BuoyDto getGuidePageBuoy(Long buoyId, GuidePageDto guidePage, boolean custom, IndexReq req) throws ActivityException {
            if (custom) {
                buoyId = TempFunction.CUSTOM_BUOY_ID;//定制出 特定浮标id
            }
            BuoyDto buoy = null;
            Map<Long, BuoyDto> buoyDtoMap = EntityUtil.transf(activityService.selectOpenBuoyList(), BuoyDto::getId);

            List<Long> buoyList = Lists.newArrayList();

            // 固定广告位定制浮标需求
            if (guidePage != null) {
                buoyList = guidePage.getBuoyList();
                if (TempFunction.isTmpDemandSlot(req.getSlotId()) && !CollectionUtils.isEmpty(buoyList) && buoyList.size() - 4 == 0) {
                    buoyList.sort((a, b) -> a.compareTo(b));
                    buoy = buoyDtoMap.get(buoyList.get(StyleTypeUtil.quarter(req.getStyleType()).intValue() - 1));
                    if (null != buoy) {
                        return buoy;
                    }
                }
            }

            if (null != buoyId) {
                buoy = buoyDtoMap.get(buoyId);
                if (null != buoy) {
                    return buoy;
                }
            }

            if (null == guidePage) {
                return null;
            }

            Collections.shuffle(buoyList);
            for (Long id : buoyList) {
                buoy = buoyDtoMap.get(id);
                if (null != buoy) {
                    return buoy;
                }
            }
            return null;
        }
    }
}
