/**
 * Project Name:tuia-youtui-web<br>
 * File Name:ActivityBOImpl.java<br>
 * Package Name:com.duiba.tuia.youtui.web.bo.impl<br>
 * Date:2017年1月17日下午4:16:48<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.dto.item.ItemDto;
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.util.MathUtil;
import cn.com.duiba.tuia.ssp.center.api.dto.SlotDto;
import cn.com.duibaboot.ext.autoconfigure.accesslog.AccessLogFilter;
import cn.com.tuia.advert.model.QueryAdvertRsp;
import com.alibaba.fastjson.JSONObject;
import com.duiba.tuia.youtui.web.bo.JoinActivityBO;
import com.duiba.tuia.youtui.web.constant.*;
import com.duiba.tuia.youtui.web.constant.ErrorCode;
import com.duiba.tuia.youtui.web.constant.datas.AdvertLayerData;
import com.duiba.tuia.youtui.web.embed.DcmBuilder;
import com.duiba.tuia.youtui.web.embed.DuibaMonitor;
import com.duiba.tuia.youtui.web.embed.Embed;
import com.duiba.tuia.youtui.web.embed.LotteryEmbed;
import com.duiba.tuia.youtui.web.exception.ActivityException;
import com.duiba.tuia.youtui.web.model.req.DoJoinActivityReq;
import com.duiba.tuia.youtui.web.model.req.IndexReq;
import com.duiba.tuia.youtui.web.service.*;
import com.duiba.tuia.youtui.web.tongdun.FraudApiInvoker;
import com.duiba.tuia.youtui.web.tongdun.FraudApiRequest;
import com.duiba.tuia.youtui.web.tool.*;
import com.google.common.collect.Maps;
import org.apache.commons.lang.math.RandomUtils;
import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.*;
import java.util.concurrent.ExecutorService;


/**
 * ClassName: ActivityBOImpl <br/>
 * Function: 参与活动业务编排实现. <br/>
 * date: 2017年1月17日 下午4:16:48 <br/>
 *
 * @author leiliang
 * @since JDK 1.6
 */
@Service
public class JoinActivityBOImpl extends BaseCacheService implements JoinActivityBO {

    @Resource
    private ExecutorService executorService;        // 定义线程池，异步化参加活动流程

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

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

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

    @Autowired
    private FraudApiInvoker fraudApiInvoker;

    @Autowired
    private PrizeService prizeService;

    @Autowired
    private SkinService skinService;

    @Autowired
    private CommonService commonService;

    @Autowired
    private TokenService tokenService;

    @Autowired
    private ContactPlateService contactPlateService;

    @Autowired
    private SlotService slotService;

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

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


    /**
     * Do join.
     *
     * @param doJoinActivityReq the do join activity req
     * @return the long
     * @throws ActivityException the activity exception
     */
    @Override
    public JSONObject doJoin(HttpServletRequest request, DoJoinActivityReq doJoinActivityReq) throws ActivityException {


        //0.防刷验证
        // 刷券行为，直接屏蔽
        if (null != doJoinActivityReq.getUserAgent() && doJoinActivityReq.getUserAgent().toLowerCase().contains("java")) {
            throw new ActivityException(ErrorCode.E0120005.geteCode(), ErrorCode.E0120005.geteDesc());
        }
        // 校验token
        String token = request.getParameter("token");
        //token验证
        if (!tokenService.checkAndInvalidConsumerTokenFromCache(doJoinActivityReq.getConsumerId(), token)) {
            throw new ActivityException(ErrorCode.E0120004.geteCode(), ErrorCode.E0120004.geteDesc());
        }

        // 1.活动验证
        TuiaActivityDto activityDto;
        try {
            activityDto = activityService.getActivityById(doJoinActivityReq.getActivityId());
            // 1.1.获取皮肤类型
            doJoinActivityReq.setActivityType(activityDto.getActivityType());

            // 1.2.打印参与活动ID和type，用于统计参与，避免从refer中获取的activityID不准问题。
            AccessLogFilter.putExPair("activityId", String.valueOf(doJoinActivityReq.getActivityId()));
            AccessLogFilter.putExPair("activityType", String.valueOf(doJoinActivityReq.getActivityType()));
            //增加地域信息
            AccessLogFilter.putExPair("area_code", this.slotService.findRegionByIp(doJoinActivityReq.getIp()));
            //记录活动参与的链路
            directPageSourceService.log(RequestLocal.get().getCid());
        } catch (Exception e) {
            logger.info("获取活动验证失败,活动获取不到或活动已删除", e);
            throw new ActivityException(ErrorCode.E0120001.geteCode(), ErrorCode.E0120001.geteDesc());
        }

        // 2.用户验证
        int joinTimes = commonService.checkConsumer(doJoinActivityReq.getActivityId(), doJoinActivityReq.getConsumerId(), activityDto.getLimitCount(), Scene.ACTIVITY);

        // 3.获取活动奖项
        List<ActivityOptionDto> options = activityService.selectActivityOptionsFromCache(doJoinActivityReq.getActivityId());

        try {
            // 4.生成订单
            RspOrder rspOrder = activityOrderService.createOrder(doJoinActivityReq, activityDto);

            // 5.异步中奖
            commonService.doJoin(rspOrder, doJoinActivityReq, options);

            // 6 .构建抽奖订单结果 , 返回订单ID和结果状态
            JSONObject result = new JSONObject();

            // 6.2更新活动参与pv
            activityService.updateDojoinPvCache(activityDto.getId());

            result.put("limitTimes", activityDto.getLimitCount() - joinTimes);

            result.put("limitType",
                    StringUtils.equals(LimitType.FOREVER.getCode(), activityDto.getLimitScope()) ? LimitType.FOREVER.getType() : LimitType.EVERYDAY.getType());
            result.put("orderId", rspOrder.getOrderId());
            result.put("success", true);
            result.put("message", "成功");
            // 6.4.设置是否需要展示浮标字段
            Optional<SlotDto> optional = this.slotService.getSlot(doJoinActivityReq.getSlotId());
            String styleTypeStr = request.getParameter("styleType");
            long styleType = StringUtils.isEmpty(styleTypeStr) ? 1L : Long.parseLong(styleTypeStr);
            result.put("isShowBuoy", optional.isPresent() && activityOrderService.isShowBuoy(activityDto, optional.get(), doJoinActivityReq.getConsumerId(), joinTimes, styleType));
            //6.5设置是否需要展示下拉推荐位
            result.put("isPullDown", activityService.isPullDown(doJoinActivityReq.getSlotId(), doJoinActivityReq.getActivityId(), joinTimes));

            return result;
        } catch (ActivityException e) {
            logger.error("发生内部错误, because of=[{}]", e.getStackTrace().toString());
            throw new ActivityException(e.getCode(), e.getMessage());
        } catch (Exception e) {
            logger.warn("用户参与活动失败.", e);
            throw new ActivityException(ErrorCode.E0120003.geteCode(), ErrorCode.E0120003.geteDesc());
        }

    }

    /**
     * 获取活动结果 showVersion 展示版本 false：旧弹层 ； true：新弹层
     *
     * @throws ActivityException
     */
    @Override
    public JSONObject result(HttpServletRequest request, String orderId, Boolean showVersion) throws ActivityException {

        try {

            //0.防刷验证
            // 刷券行为，直接屏蔽
            if (null != RequestTool.getUserAgent(request) && RequestTool.getUserAgent(request).toLowerCase().contains("java")) {
                throw new ActivityException(ErrorCode.E0120005.geteCode(), ErrorCode.E0120005.geteDesc());
            }
            // 1.缓存获取参数
            Long appId = RequestLocal.get().getAppId();
            Long consumerId = RequestLocal.get().getCid();

            // 2.构建奖项结果
            return buildResultRsp(request, orderId, appId, consumerId, showVersion);
        } catch (ActivityException e) {
            logger.warn("活动工具－获取参与结果异常", e);
            throw new ActivityException(e.getCode(), e.getMessage());
        }
    }

    /**
     * 构建抽奖结果.
     *
     * @return the JSON object
     * @throws ActivityException the activity exception
     */
    private JSONObject buildResultRsp(HttpServletRequest request, String orderId, Long appId, Long consumerId,
                                      Boolean showVersion) throws ActivityException {
        Map<String, Object> lottery = Maps.newHashMap();
        JSONObject jsonObject = new JSONObject();


        // 如果没有新弹层，默认false
        if (null == showVersion) {
            showVersion = false;
        }
        ActivityOrderDto activityOrderDto = checkOrderAndConsumer(orderId, consumerId);


        // 2.3 根据奖项ID，奖项类型，判断中奖流程是否走完。 返回成功、失败、等待三种状态
        if (checkWaitStatus(jsonObject, activityOrderDto)) {
            return jsonObject;
        }

        String orderOptionType = activityOrderDto.getPrizeType();
        lottery = getStringObjectMap(request, appId, consumerId, showVersion, lottery, jsonObject, activityOrderDto);

        // 7.奖项ID和奖项类型,订单ID
        lottery.put("id", activityOrderDto.getPrizeId());
        lottery.put("type", orderOptionType);
        jsonObject.put("orderId", orderId);
        jsonObject.put("activityId", activityOrderDto.getActivityId());

        // 8.图片url 域名切换
        Object imgUrl = lottery.get(Constants.VALUENAME.IMG_URL);
        if (imgUrl != null) {
            String url = imgUrl.toString();
            lottery.put(Constants.VALUENAME.IMG_URL, DomainUtil.replaceDomain(url, DomainUtil.getCurrentYunDomain(request)));
        }
        jsonObject.put("lottery", lottery);
        jsonObject.put("status", "success");

        // 9.客服信息模版
        ContactPlateDto contactPlateDto = contactPlateService.getDtoByHost(request.getHeader("host"));
        if (contactPlateDto != null) {
            Map<String, Object> detailContactInfo = Maps.newHashMap();
            detailContactInfo.put("isOpenOptionDetail", contactPlateDto.getIsOpenOptionDetail());
            detailContactInfo.put("optionDetailPhone", contactPlateDto.getOptionDetailPhone());
            jsonObject.put("detailContactInfo", detailContactInfo);
        }
        AccessLogFilter.putExPair("prizeType", activityOrderDto.getPrizeType());

        return jsonObject;
    }

    private boolean checkWaitStatus(JSONObject jsonObject, ActivityOrderDto activityOrderDto) {
        if (null == activityOrderDto.getPrizeType() || "null".equals(String.valueOf(activityOrderDto.getPrizeType()))
                || StringUtils.isBlank(String.valueOf(activityOrderDto.getPrizeType()))) {
            jsonObject.put("status", "wait");
            jsonObject.put("message", "成功-等待");
            return true;
        }
        return false;
    }

    private Map<String, Object> getStringObjectMap(HttpServletRequest request, Long appId, Long consumerId, Boolean showVersion, Map<String, Object> lottery, JSONObject jsonObject, ActivityOrderDto activityOrderDto) throws ActivityException {
        String orderId = activityOrderDto.getOrderId();
        String orderOptionType = activityOrderDto.getPrizeType();
        String skinType = request.getParameter(Constants.VALUENAME.SKIN_TYPE);
        if (StringUtils.isNotBlank(skinType)) {
            lottery.put(Constants.VALUENAME.SKIN_TYPE, skinType);
        }
        if (ActivityOptionType.TYPE_THANKS.getCode().equals(orderOptionType)) {
            // 3.1 如果为谢谢参与
            jsonObject.put("result", Constants.LOTTERYCODE.LOTTERY_CODE_0);
            lottery = commonService.getThankRecommend(consumerId, request);

        } else if (ActivityOptionType.TYPE_AGAIN.getCode().equals(orderOptionType)) {
            // 3.2 如果为再来一次
            jsonObject.put("result", Constants.LOTTERYCODE.LOTTERY_CODE_1);
            jsonObject.put("againTag", orderId);
        } else if (ActivityOptionType.TYPE_LUCKY.getCode().equals(orderOptionType)
                || ActivityOptionType.TYPE_COUPON.getCode().equals(orderOptionType)) {
            // 4.如果奖项是福袋或者推啊券
            QueryAdvertRsp advert = getQueryAdvertRsp(orderId, consumerId, lottery, jsonObject, activityOrderDto);


            // 5.构造同盾决策引擎请求，放入请求队列中处理
            Cookie rid = CookieUtil.getCookieByName(request, "_coll_rid");
            if (null != rid) {
                fraudApiInvoker.invoke((buildFraudApiReq(request, activityOrderDto, rid.getValue())));
            }
            buildDoJoinRspForTuiaCoupon(request, lottery, activityOrderDto, appId, consumerId, advert,
                    activityOrderDto.getActivityId(), showVersion);
        } else {
            //6.构建特殊奖项信息（非广告券）
            buildDoJoinRspForSpecail(request, consumerId, orderId, orderOptionType, lottery, jsonObject);

        }
        return lottery;
    }

    private void buildDoJoinRspForSpecail(HttpServletRequest request, Long consumerId, String orderId, String orderOptionType,
                                          Map<String, Object> lottery, JSONObject jsonObject) throws ActivityException {
        if (ActivityOptionType.TYPE_PHYSICAL.getCode().equals(orderOptionType)) {

            // 6.构造实物奖项中奖结果
            AlipayOrderDto physicalOrder = activityOrderService.selectAlipayOrder(orderId);
            if (null == physicalOrder) {
                logger.warn("无实物中奖记录信息。physicalOrder  is null ");
                throw new ActivityException(ErrorCode.E0120011.geteCode(), ErrorCode.E0120011.geteDesc());
            }
            jsonObject.put("result", Constants.LOTTERYCODE.LOTTERY_CODE_2);

            buildDoJoinRspForPhysical(request, lottery, physicalOrder, consumerId);

        } else if (ActivityOptionType.TYPE_ALIPAY.getCode().equals(orderOptionType)) {
            // 7 中支付宝红包奖项中奖结果

            // 7.1 查询支付宝转账记录
            AlipayOrderDto alipayOrder = activityOrderService.selectAlipayOrder(orderId);
            if (null == alipayOrder) {
                logger.warn("无支付宝转账记录信息。alipayOrderDto  is null ");
                throw new ActivityException(ErrorCode.E0120011.geteCode(), ErrorCode.E0120011.geteDesc());
            }
            jsonObject.put("result", Constants.LOTTERYCODE.LOTTERY_CODE_2);

            buildDoJoinRspForAlipay(request, lottery, alipayOrder, consumerId);
        } else if (ActivityOptionType.TYPE_VIRTUAL.getCode().equals(orderOptionType)) {
            //8.构造虚拟奖品中奖结果
            AlipayOrderDto virtualOrder = activityOrderService.selectAlipayOrder(orderId);
            if (null == virtualOrder) {
                logger.warn("无虚拟奖品中奖记录信息。physicalOrder  is null ");
                throw new ActivityException(ErrorCode.E0120011.geteCode(), ErrorCode.E0120011.geteDesc());
            }
            jsonObject.put("result", Constants.LOTTERYCODE.LOTTERY_CODE_2);
            buildDoJoinRspForVirtual(request, lottery, virtualOrder, consumerId);
        } else if (ActivityOptionType.TYPE_QB.getCode().equals(orderOptionType)) {
            //9.构造qb奖品中奖结果
            AlipayOrderDto qbOrder = activityOrderService.selectAlipayOrder(orderId);
            if (null == qbOrder) {
                logger.warn("无实物中奖记录信息。qbOrder  is null ");
                throw new ActivityException(ErrorCode.E0120011.geteCode(), ErrorCode.E0120011.geteDesc());
            }
            jsonObject.put("result", Constants.LOTTERYCODE.LOTTERY_CODE_2);
            buildDoJoinRspForQb(request, lottery, qbOrder, consumerId);
        } else if (ActivityOptionType.TYPE_BILL.equalsCode(orderOptionType)) {
            //10.构造话费奖品中奖结果
            AlipayOrderDto billOrder = activityOrderService.selectAlipayOrder(orderId);
            if (null == billOrder) {
                logger.warn("无话费奖品中奖记录信息. billOrder is null");
                throw new ActivityException(ErrorCode.E0120011.geteCode(), ErrorCode.E0120011.geteDesc());
            }
            jsonObject.put("result", Constants.LOTTERYCODE.LOTTERY_CODE_2);
            buildDoJoinRspForBill(request, lottery, billOrder, consumerId);//埋点相关
        }
    }

    private void buildDoJoinRspForQb(HttpServletRequest request, Map<String, Object> lottery,
                                     AlipayOrderDto qbOrderDto, Long consumerId) {

        ActivityOptionDto activityOptionDto = activityService.selectActivityOption(qbOrderDto.getPrizeId());
        PrizeDto prizeDto = prizeService.selectPrizeById(activityOptionDto.getPrizeId());
        int qbType = qbOrderDto.getAlipayType();
        lottery.put("amount", qbOrderDto.getAwardAmount() / prizeDto.getPrizeValue());//中奖金额
        lottery.put("subType", qbType);//1:定额,2:随机
        lottery.put("id", qbOrderDto.getPrizeId());//奖项id
        lottery.put(Constants.VALUENAME.IMG_URL, prizeDto.getDetailImage());//实物奖品
        lottery.put("type", ActivityOptionType.TYPE_ALIPAY.getCode());
        lottery.put("title", "Q币");
        lottery.put("prizeRecommendContent", null == prizeDto.getPrizeRecommendContent() ? PrizeDto.DEFAULPRIZERECOMMENDCONTENT : prizeDto.getPrizeRecommendContent());
        if (qbOrderDto.getAliAccount() != null) {
            lottery.put("aliAccount", qbOrderDto.getAliAccount());
        }
        Long appId = qbOrderDto.getAppId();
        String host = "//" + request.getHeader("host");
        String dcm = DpmInfo.dcmClickInfo(Constants.DCM.DCM_A_1017, (long) Constants.DCM.DCM_B_0, 21 == qbType ? String.valueOf(this.skinService.selectQbQuotaLayerId()) : String.valueOf(this.skinService.selectQbRandomLayerId()), (long) (21 == qbType ? 1 : 2));

        //出奖页埋点信息
        Map<String, Object> page1 = new HashMap<>();

        String dpmBtnClick = DuibaMonitor.build(appId, Constants.DPM.DPM_B_112, Constants.DPM.DPM_C_1, Constants.DPM.DPM_D_3);
        String dpmBtnClose = DuibaMonitor.build(appId, Constants.DPM.DPM_B_112, Constants.DPM.DPM_C_1, Constants.DPM.DPM_D_1);
        String dpmExposure = DuibaMonitor.build(appId, Constants.DPM.DPM_B_112, Constants.DPM.DPM_C_1, Constants.DPM.DPM_D_0);
        String dpmImgClick = DuibaMonitor.build(appId, Constants.DPM.DPM_B_112, Constants.DPM.DPM_C_1, Constants.DPM.DPM_D_2);

        Embed embed = new LotteryEmbed(dcm, null, null, consumerId, appId, host, qbOrderDto.getActivityType());
        page1.put(Embed.ST_INFO_DPM_CLICK, embed.setDpm(dpmBtnClick).buildClickEmbed());
        page1.put(Embed.ST_INFO_DPM_CLOSE, embed.setDpm(dpmBtnClose).buildClickEmbed());
        page1.put(Embed.ST_INFO_DPM_EXPOSURE, embed.setDpm(dpmExposure).buildExposureEmbed());
        page1.put("st_info_dpm_img_click", embed.setDpm(dpmImgClick).buildClickEmbed());
        lottery.put("page1", page1);

        //信息填写页埋点信息
        Map<String, Object> page2 = new HashMap<>();
        dpmBtnClick = DuibaMonitor.build(appId, Constants.DPM.DPM_B_112, Constants.DPM.DPM_C_2, Constants.DPM.DPM_D_3);
        dpmBtnClose = DuibaMonitor.build(appId, Constants.DPM.DPM_B_112, Constants.DPM.DPM_C_2, Constants.DPM.DPM_D_1);
        dpmExposure = DuibaMonitor.build(appId, Constants.DPM.DPM_B_112, Constants.DPM.DPM_C_2, Constants.DPM.DPM_D_0);
        page2.put(Embed.ST_INFO_DPM_BTN_GET, embed.setDpm(dpmBtnClick).buildClickEmbed());
        page2.put(Embed.ST_INFO_DPM_BTN_CLOSE, embed.setDpm(dpmBtnClose).buildClickEmbed());
        page2.put(Embed.ST_INFO_DPM_EXPOSURE, embed.setDpm(dpmExposure).buildExposureEmbed());
        lottery.put("page2", page2);

        //中奖结果页埋点信息
        Map<String, Object> page3 = new HashMap<>();
        String dcmBtnClick = DuibaMonitor.build(Constants.DCM.DCM_A_1010, Constants.DCM.DCM_B_0, Constants.DCM.DCM_C_0, Constants.DCM.DCM_D_0);
        dpmBtnClick = DuibaMonitor.build(appId, Constants.DPM.DPM_B_112, Constants.DPM.DPM_C_3, Constants.DPM.DPM_D_2);
        dpmBtnClose = DuibaMonitor.build(appId, Constants.DPM.DPM_B_112, Constants.DPM.DPM_C_3, Constants.DPM.DPM_D_1);
        dpmExposure = DuibaMonitor.build(appId, Constants.DPM.DPM_B_112, Constants.DPM.DPM_C_3, Constants.DPM.DPM_D_0);
        page3.put(Embed.ST_INFO_DPM_EXPOSURE, embed.setDpm(dpmExposure).buildExposureEmbed());
        page3.put(Embed.ST_INFO_DPM_BTN_CLOSE, embed.setDpm(dpmBtnClose).buildClickEmbed());
        page3.put(Embed.ST_INFO_DPM_BTN_GET, embed.setDcm(dcmBtnClick).setDpm(dpmBtnClick).buildClickEmbed());

        lottery.put("page3", page3);
    }

    private void buildDoJoinRspForVirtual(HttpServletRequest request, Map<String, Object> lottery, AlipayOrderDto virtualOrder, Long consumerId) {
        ActivityOptionDto activityOptionDto = activityService.selectActivityOption(virtualOrder.getPrizeId());
        PrizeDto prizeDto = prizeService.selectPrizeById(activityOptionDto.getPrizeId());//查询奖项绑定的奖品
        Integer alipayType = virtualOrder.getAlipayType();
        lottery.put("id", virtualOrder.getPrizeId());//奖项id
        lottery.put("type", ActivityOptionType.TYPE_VIRTUAL.getCode());
        lottery.put(Constants.VALUENAME.IMG_URL, prizeDto.getDetailImage());
        lottery.put("layerImgUrl", activityOptionDto.getImage());//250*250
        lottery.put("title", virtualOrder.getPrizeTitle());
        lottery.put("prizeRecommendContent", null == prizeDto.getPrizeRecommendContent() ? PrizeDto.DEFAULPRIZERECOMMENDCONTENT : prizeDto.getPrizeRecommendContent());

        //获取dsm
        String dsm = buildDsm(virtualOrder.getActivityId(), virtualOrder.getActivityType(), request);

        if (AlipayType.isVirtualApi(alipayType)) {
            lottery.put("subType", AlipayType.VIRTUAL_API.getType());
            lottery.put("prizeIdent", prizeDto.getApiRechargeDto() == null ? "" : prizeDto.getApiRechargeDto().getPrizeIdent());
            lottery.put("context", virtualOrder.getContextArray());
            lottery.put("awardAmount", virtualOrder.getPrizeWorth());
            lottery.put("valueUnit", prizeDto.getApiRechargeDto().getValueUnit());
        } else if (AlipayType.isVirtualTicket(alipayType)) {
            lottery.put("subType", AlipayType.VIRTUAL_TICKET.getType());
            CouponsCodeDto coupon = virtualOrder.getCoupon();
            if (coupon != null) {
                lottery.put("code", coupon.getCouponsCode());
                lottery.put("password", coupon.getCouponsPwd());
                lottery.put("couponInfo", prizeDto.getCouponsCodeDto().getUseInfo());
                lottery.put("linkUrl", coupon.getLinkInfo());
            }
        } else if (AlipayType.VIRTUAL_ACCOUNT.getType().equals(alipayType)) {
            lottery.put("subType", AlipayType.VIRTUAL_ACCOUNT.getType());
            lottery.put("context", virtualOrder.getContextArray());
        } else if (AlipayType.VIRTUAL_RED_PACKET.getType().equals(alipayType)) {
            IndexReq req = new IndexReq();
            req.setHost(request.getHeader("host"));
            req.setLogin(LoginType.NORMAL.getCode());
            req.setSlotId(virtualOrder.getSlotId());
            req.setDeviceId(virtualOrder.getDeviceId());
            req.setAppKey(RequestLocal.get().getAppKey());//许确认
            req.setActivityId(virtualOrder.getActivityId());
            req.setDsm(dsm);
            req.setDcm(DcmBuilder.directFixedBlockBuild(prizeDto.getRedPacket().getPageId()));

            lottery.put("subType", alipayType);
            lottery.put("linkUrl", PathUtil.getGuidePageUrl(prizeDto.getRedPacket().getPageId(), req, PageType.DIRECT.getCode()));

        }

        Long appId = virtualOrder.getAppId();
        String host = "//" + request.getHeader("host");

        //奖品领取页
        Map<String, Object> page1 = new HashMap<>();
        String dpmBtnClick = DuibaMonitor.build(appId, Constants.DPM.DPM_B_111, Constants.DPM.DPM_C_1, Constants.DPM.DPM_D_1);
        String dpmBtnClose = DuibaMonitor.build(appId, Constants.DPM.DPM_B_111, Constants.DPM.DPM_C_1, Constants.DPM.DPM_D_2);
        String dpmExposure = DuibaMonitor.build(appId, Constants.DPM.DPM_B_111, Constants.DPM.DPM_C_1, Constants.DPM.DPM_D_0);

        Embed embed = new LotteryEmbed(null, null, null, consumerId, appId, host, virtualOrder.getActivityType());

        page1.put("st_info_btn_click", embed.setDpm(dpmBtnClick).buildClickEmbed());
        page1.put("st_info_btn_close", embed.setDpm(dpmBtnClose).buildClickEmbed());
        page1.put("st_info_exposure", embed.setDpm(dpmExposure).buildExposureEmbed());
        lottery.put("page1", page1);

        //虚拟奖品结果页
        Map<String, Object> page2 = new HashMap<>();
        dpmBtnClick = DuibaMonitor.build(appId, Constants.DPM.DPM_B_111, Constants.DPM.DPM_C_2, Constants.DPM.DPM_D_1);
        String dcmBtnClick = DuibaMonitor.build(Constants.DCM.DCM_A_1010, Constants.DCM.DCM_B_0, Constants.DCM.DCM_C_0, Constants.DCM.DCM_D_0);
        dpmBtnClose = DuibaMonitor.build(appId, Constants.DPM.DPM_B_111, Constants.DPM.DPM_C_2, Constants.DPM.DPM_D_4);
        dpmExposure = DuibaMonitor.build(appId, Constants.DPM.DPM_B_111, Constants.DPM.DPM_C_2, Constants.DPM.DPM_D_0);
        page2.put("st_info_btn_click", embed.setDpm(dpmBtnClick).buildClickEmbed());
        page2.put("st_info_btn_close", embed.setDpm(dpmBtnClose).buildClickEmbed());
        page2.put("st_info_exposure", embed.setDcm(dcmBtnClick).setDpm(dpmExposure).buildExposureEmbed());
        lottery.put("page2", page2);
    }

    private void buildDoJoinRspForPhysical(HttpServletRequest request, Map<String, Object> lottery, AlipayOrderDto physicalOrder, Long consumerId) {
        ActivityOptionDto activityOptionDto = activityService.selectActivityOption(physicalOrder.getPrizeId());
        PrizeDto prizeDto = prizeService.selectPrizeById(activityOptionDto.getPrizeId());//查询奖项绑定的奖品n
        lottery.put("id", physicalOrder.getPrizeId());//奖项id
        lottery.put("type", ActivityOptionType.TYPE_PHYSICAL.getCode());
        lottery.put(Constants.VALUENAME.IMG_URL, prizeDto.getDetailImage());//640*300
        lottery.put("layerImgUrl", activityOptionDto.getImage());//250*250
        lottery.put("title", physicalOrder.getPrizeTitle());
        lottery.put("prizeRecommendContent", null == prizeDto.getPrizeRecommendContent() ? PrizeDto.DEFAULPRIZERECOMMENDCONTENT : prizeDto.getPrizeRecommendContent());
        Long appId = physicalOrder.getAppId();

        //获取dsm
        String dsm = buildDsm(physicalOrder.getActivityId(), physicalOrder.getActivityType(), request);
        JSONObject commonInfo = DpmInfo.setCommonEmbedForAliPay(appId, consumerId, physicalOrder, dsm);
        String host = "//" + request.getHeader("host");

        Map<String, Object> page1 = new HashMap<>();
        page1.put("st_info_exposure", DpmInfo.setExposureEmbedForAliPay(commonInfo, host, DpmInfo.getDpmInfo(appId, Constants.DPM.DPM_B_109, Constants.DPM.DPM_C_1, Constants.DPM.DPM_D_0), null));
        page1.put("st_info_click_btn_close", DpmInfo.setClickInfoEmbedForAliPay(commonInfo, host, DpmInfo.getDpmInfo(appId, Constants.DPM.DPM_B_109, Constants.DPM.DPM_C_1, Constants.DPM.DPM_D_2), null));
        page1.put("st_info_click_btn_save", DpmInfo.setClickInfoEmbedForAliPay(commonInfo, host, DpmInfo.getDpmInfo(appId, Constants.DPM.DPM_B_109, Constants.DPM.DPM_C_1, Constants.DPM.DPM_D_1), null));
        lottery.put("page1", page1);

        Map<String, Object> page2 = new HashMap<>();
        page2.put("st_info_exposure", DpmInfo.setExposureEmbedForAliPay(commonInfo, host, DpmInfo.getDpmInfo(appId, Constants.DPM.DPM_B_109, Constants.DPM.DPM_C_2, Constants.DPM.DPM_D_0), null));
        page2.put("st_info_click_btn_close", DpmInfo.setClickInfoEmbedForAliPay(commonInfo, host, DpmInfo.getDpmInfo(appId, Constants.DPM.DPM_B_109, Constants.DPM.DPM_C_2, Constants.DPM.DPM_D_4), null));
        String dcm = DpmInfo.dcmInfo(Constants.DCM.DCM_A_1010, 0L, 0, 0L);
        page2.put("st_info_click_btn_record", DpmInfo.setClickInfoEmbedForAliPay(commonInfo, host, DpmInfo.getDpmInfo(appId, Constants.DPM.DPM_B_109, Constants.DPM.DPM_C_2, Constants.DPM.DPM_D_1), dcm));
        lottery.put("page2", page2);
    }

    private ActivityOrderDto checkOrderAndConsumer(String orderId, Long consumerId) throws ActivityException {
        // 1.检查用户信息
        if (null == consumerId || StringUtils.isEmpty(String.valueOf(consumerId))) {
            logger.info("用户信息异常。ConsumerId is null");
            throw new ActivityException(ErrorCode.E0120006.geteCode(), ErrorCode.E0120006.geteDesc());
        }

        // 2.校验订单号
        if (!checkOrderId(orderId)) {
            logger.info("订单号异常。不符合订单号规则orderId is error   and order id is " + orderId);
            throw new ActivityException(ErrorCode.E0120007.geteCode(), ErrorCode.E0120007.geteDesc());
        }

        // 3.通过(用户ID和订单ID)查询订单信息
        ActivityOrderDto activityOrderDto = activityOrderService.selectByIdAndConsumerId(orderId, consumerId);
        // 3.1 校验权限(用户信息仅用于查询订单时分表)
        if (null != activityOrderDto && null != activityOrderDto.getConsumerId()
                && !activityOrderDto.getConsumerId().equals(consumerId)) {
            logger.info("权限异常，访问用户和下单用户ID不一致。consumerId not  equals activityOrderDto.getConsumerId()");
            throw new ActivityException(ErrorCode.E0120009.geteCode(), ErrorCode.E0120009.geteDesc());
        }
        // 3.2 是否有订单信息
        if (null == activityOrderDto) {
            logger.info("无订单信息。activityOrderDto  is null ");
            throw new ActivityException(ErrorCode.E0120008.geteCode(), ErrorCode.E0120008.geteDesc());
        }
        return activityOrderDto;
    }

    /**
     * checkOrderId:(这里用一句话描述这个方法的作用). <br/>
     *
     * @param orderId
     * @return
     */
    private Boolean checkOrderId(String orderId) throws ActivityException {
        // 1.订单号非空和长度校验
        if (null == orderId || orderId.length() < 5 || orderId.length() > 19) {
            logger.error("非法订单号，error  orderId is " + orderId);
            return false;
        }

        // 2.截取orderId 获取后四位，作为表后缀校验
        String orderIdSuffix = orderId.substring(orderId.length() - 4);
        Long orederTb = Long.valueOf(orderIdSuffix);

        return orederTb < 1024;
    }

    private QueryAdvertRsp getQueryAdvertRsp(String orderId, Long ConsumerId, Map<String, Object> lottery, JSONObject jsonObject, ActivityOrderDto activityOrderDto) throws ActivityException {
        // 4.1查询奖项信息
        if (null == activityOrderDto.getPrizeId()) {
            JSONObject json = JSONObject.parseObject(activityOrderDto.getCouponData());
            // 4.2构建奖项信息, "使用详情"链接
            lottery.put(Constants.VALUENAME.IMG_URL, json.get(Constants.VALUENAME.THUMBNAIL_PNG));
            lottery.put("isDownloadUrl", true);
            lottery.put("linkTo", ItemDto.LinkToBussiness);
            lottery.put("title", json.get(Constants.VALUENAME.TITLE));
        } else {
            ActivityOptionDto orderOptionDto = activityService.selectActivityOption(activityOrderDto.getPrizeId());
            // 4.2构建奖项信息, "使用详情"链接
            lottery.put(Constants.VALUENAME.IMG_URL, orderOptionDto.getImage());
            lottery.put("isDownloadUrl", true);
            lottery.put("linkTo", ItemDto.LinkToBussiness);
            lottery.put("title", orderOptionDto.getTitle());
        }
        // 4.3推啊券的构造抽奖结果
        jsonObject.put("result", Constants.LOTTERYCODE.LOTTERY_CODE_2);
        Long slotId = null;
        if (StringUtils.isNotBlank(RequestLocal.get().getSlotId())) {
            slotId = Long.valueOf(RequestLocal.get().getSlotId());
        }
        QueryAdvertRsp advert = luckBagService.queryAdvert(ConsumerId, orderId, 0, slotId);
        if (null == advert) {
            logger.warn("查询广告信息失败。JoinActivityBOImpl---》buildResultRsp---》queryAdvert is null");
            throw new ActivityException(ErrorCode.E0120012.geteCode(), ErrorCode.E0120012.geteDesc());
        }
        return advert;
    }

    private void buildDoJoinRspForAlipay(HttpServletRequest request, Map<String, Object> lottery,
                                         AlipayOrderDto alipayOrderDto, Long consumerId) {
        int alipayType = alipayOrderDto.getAlipayType();
        ActivityOptionDto activityOptionDto = activityService.selectActivityOption(alipayOrderDto.getPrizeId());
        PrizeDto prizeDto = prizeService.selectPrizeById(activityOptionDto.getPrizeId());//查询奖项绑定的奖品n
        lottery.put("amount", MathUtil.fen2Yuan(alipayOrderDto.getAwardAmount()));//中奖金额
        lottery.put("subType", alipayType);//1:定额,2:随机
        lottery.put("id", alipayOrderDto.getPrizeId());//奖项id
        lottery.put("type", ActivityOptionType.TYPE_ALIPAY.getCode());
        lottery.put(Constants.VALUENAME.IMG_URL, "//yun.tuia.cn/h5-tuia/couponPrize/alipay/alipay.png");//640*300
        lottery.put("title", "支付宝红包");
        lottery.put("prizeRecommendContent", null == prizeDto.getPrizeRecommendContent() ? PrizeDto.DEFAULPRIZERECOMMENDCONTENT : prizeDto.getPrizeRecommendContent());
        if (alipayOrderDto.getAliAccount() != null && alipayOrderDto.getAliName() != null) {
            lottery.put("aliAccount", alipayOrderDto.getAliAccount());
            lottery.put("aliName", alipayOrderDto.getAliName());
        }
        Long appId = alipayOrderDto.getAppId();
        //3.3dsm以及deliverType
        //3.4 获取dsm以及deliverType
        String dsm = buildDsm(alipayOrderDto.getActivityId(), alipayOrderDto.getActivityType(), request);
        JSONObject commonInfo = DpmInfo.setCommonEmbedForAliPay(appId, consumerId, alipayOrderDto, dsm);
        String host = "//" + request.getHeader("host");
        String dcm = DpmInfo.dcmClickInfo(Constants.DCM.DCM_A_1001, (long) Constants.DCM.DCM_B_0, 1 == alipayType ? String.valueOf(this.skinService.selectAlipayQuotaLayerId()) : String.valueOf(this.skinService.selectAlipayRandomLayerId()), (long) alipayType);

        //出奖页埋点信息
        Map<String, Object> page1 = new HashMap<>();

        page1.put(Embed.ST_INFO_DPM_EXPOSURE, DpmInfo.setExposureEmbedForAliPay(commonInfo, host, DpmInfo.getDpmInfo(appId, Constants.DPM.DPM_B_46, Constants.DPM.DPM_C_1, Constants.DPM.DPM_D_0), dcm));
        page1.put(Embed.ST_INFO_DPM_BTN_CLOSE, DpmInfo.setClickInfoEmbedForAliPay(commonInfo, host, DpmInfo.getDpmInfo(appId, Constants.DPM.DPM_B_46, Constants.DPM.DPM_C_1, Constants.DPM.DPM_D_1), dcm));
        page1.put("st_info_dpm_img_click", DpmInfo.setClickInfoEmbedForAliPay(commonInfo, host, DpmInfo.getDpmInfo(appId, Constants.DPM.DPM_B_46, Constants.DPM.DPM_C_1, Constants.DPM.DPM_D_2), dcm));
        page1.put(Embed.ST_INFO_DPM_BTN_GET, DpmInfo.setClickInfoEmbedForAliPay(commonInfo, host, DpmInfo.getDpmInfo(appId, Constants.DPM.DPM_B_46, Constants.DPM.DPM_C_1, Constants.DPM.DPM_D_3), dcm));
        lottery.put("page1", page1);

        //信息填写页埋点信息
        Map<String, Object> page2 = new HashMap<>();
        page2.put(Embed.ST_INFO_DPM_EXPOSURE, DpmInfo.setExposureEmbedForAliPay(commonInfo, host, DpmInfo.getDpmInfo(appId, Constants.DPM.DPM_B_46, Constants.DPM.DPM_C_2, Constants.DPM.DPM_D_0), dcm));
        page2.put(Embed.ST_INFO_DPM_BTN_CLOSE, DpmInfo.setClickInfoEmbedForAliPay(commonInfo, host, DpmInfo.getDpmInfo(appId, Constants.DPM.DPM_B_46, Constants.DPM.DPM_C_2, Constants.DPM.DPM_D_1), dcm));
        page2.put(Embed.ST_INFO_DPM_BTN_GET, DpmInfo.setClickInfoEmbedForAliPay(commonInfo, host, DpmInfo.getDpmInfo(appId, Constants.DPM.DPM_B_46, Constants.DPM.DPM_C_2, Constants.DPM.DPM_D_3), dcm));
        lottery.put("page2", page2);

        //中奖结果页埋点信息
        Map<String, Object> page3 = new HashMap<>();
        page3.put(Embed.ST_INFO_DPM_EXPOSURE, DpmInfo.setExposureEmbedForAliPay(commonInfo, host, DpmInfo.getDpmInfo(appId, Constants.DPM.DPM_B_46, Constants.DPM.DPM_C_3, Constants.DPM.DPM_D_0), dcm));
        page3.put(Embed.ST_INFO_DPM_BTN_CLOSE, DpmInfo.setClickInfoEmbedForAliPay(commonInfo, host, DpmInfo.getDpmInfo(appId, Constants.DPM.DPM_B_46, Constants.DPM.DPM_C_3, Constants.DPM.DPM_D_1), dcm));
        page3.put(Embed.ST_INFO_DPM_BTN_GET, DpmInfo.setClickInfoEmbedForAliPay(commonInfo, host, DpmInfo.getDpmInfo(appId, Constants.DPM.DPM_B_46, Constants.DPM.DPM_C_3, Constants.DPM.DPM_D_3), DpmInfo.dcmClickInfo(Constants.DCM.DCM_A_1010, 0L, "0", 0L)));
        lottery.put("page3", page3);
    }

    private void buildDoJoinRspForBill(HttpServletRequest request, Map<String, Object> lottery,
                                       AlipayOrderDto alipayOrderDto, Long consumerId) {
        int alipayType = alipayOrderDto.getAlipayType();
        ActivityOptionDto activityOptionDto = activityService.selectActivityOption(alipayOrderDto.getPrizeId());
        PrizeDto prizeDto = prizeService.selectPrizeById(activityOptionDto.getPrizeId());//查询奖项绑定的奖品
        lottery.put("amount", MathUtil.fen2Yuan(alipayOrderDto.getAwardAmount()));//中奖金额
        lottery.put("subType", alipayType);//31:定额,32:随机
        lottery.put("id", alipayOrderDto.getPrizeId());//奖项id
        lottery.put("type", ActivityOptionType.TYPE_BILL.getCode());
        lottery.put(Constants.VALUENAME.IMG_URL, prizeDto.getDetailImage());//640*300
        lottery.put("title", "话费");
        lottery.put("prizeRecommendContent", prizeDto.getPrizeRecommendContent());
        if (alipayOrderDto.getAliAccount() != null) {
            lottery.put("aliAccount", alipayOrderDto.getAliAccount());
        }
        Long appId = alipayOrderDto.getAppId();
        String host = "//" + request.getHeader("host");
        String dcm = DcmBuilder.billBuild(activityOptionDto.getPrizeId(), 0, AlipayType.BILL_QUOTA.getType().equals(alipayType) ? this.skinService.selectBillQuotaLayerId() : this.skinService.selectBillRandomLayerId());
        //出奖页埋点信息
        Map<String, Object> page1 = new HashMap<>();

        String dpmExposure = DuibaMonitor.build(appId, Constants.DPM.DPM_B_114, Constants.DPM.DPM_C_1, Constants.DPM.DPM_D_0);
        String dpmBtnClick = DuibaMonitor.build(appId, Constants.DPM.DPM_B_114, Constants.DPM.DPM_C_1, Constants.DPM.DPM_D_3);
        String dpmBtnClose = DuibaMonitor.build(appId, Constants.DPM.DPM_B_114, Constants.DPM.DPM_C_1, Constants.DPM.DPM_D_1);
        String dpmImgClick = DuibaMonitor.build(appId, Constants.DPM.DPM_B_114, Constants.DPM.DPM_C_1, Constants.DPM.DPM_D_2);

        Embed embed = new LotteryEmbed(dcm, null, null, consumerId, appId, host, alipayOrderDto.getActivityType());
        page1.put(Embed.ST_INFO_DPM_BTN_GET, embed.setDpm(dpmBtnClick).buildClickEmbed());
        page1.put(Embed.ST_INFO_DPM_BTN_CLOSE, embed.setDpm(dpmBtnClose).buildClickEmbed());
        page1.put(Embed.ST_INFO_DPM_EXPOSURE, embed.setDpm(dpmExposure).buildExposureEmbed());
        page1.put("st_info_dpm_img_click", embed.setDpm(dpmImgClick).buildClickEmbed());
        lottery.put("page1", page1);

        //信息填写页埋点信息
        Map<String, Object> page2 = new HashMap<>();
        dpmBtnClick = DuibaMonitor.build(appId, Constants.DPM.DPM_B_114, Constants.DPM.DPM_C_2, Constants.DPM.DPM_D_3);
        dpmBtnClose = DuibaMonitor.build(appId, Constants.DPM.DPM_B_114, Constants.DPM.DPM_C_2, Constants.DPM.DPM_D_1);
        dpmExposure = DuibaMonitor.build(appId, Constants.DPM.DPM_B_114, Constants.DPM.DPM_C_2, Constants.DPM.DPM_D_0);
        page2.put(Embed.ST_INFO_DPM_BTN_GET, embed.setDpm(dpmBtnClick).buildClickEmbed());
        page2.put(Embed.ST_INFO_DPM_BTN_CLOSE, embed.setDpm(dpmBtnClose).buildClickEmbed());
        page2.put(Embed.ST_INFO_DPM_EXPOSURE, embed.setDpm(dpmExposure).buildExposureEmbed());
        lottery.put("page2", page2);

        //中奖结果页埋点信息
        Map<String, Object> page3 = new HashMap<>();
        String dcmBtnClick = DuibaMonitor.build(Constants.DCM.DCM_A_1010, Constants.DCM.DCM_B_0, Constants.DCM.DCM_C_0, Constants.DCM.DCM_D_0);
        dpmBtnClick = DuibaMonitor.build(appId, Constants.DPM.DPM_B_114, Constants.DPM.DPM_C_3, Constants.DPM.DPM_D_2);
        dpmBtnClose = DuibaMonitor.build(appId, Constants.DPM.DPM_B_114, Constants.DPM.DPM_C_3, Constants.DPM.DPM_D_1);
        dpmExposure = DuibaMonitor.build(appId, Constants.DPM.DPM_B_114, Constants.DPM.DPM_C_3, Constants.DPM.DPM_D_0);
        page3.put(Embed.ST_INFO_DPM_EXPOSURE, embed.setDpm(dpmExposure).buildExposureEmbed());
        page3.put(Embed.ST_INFO_DPM_BTN_CLOSE, embed.setDpm(dpmBtnClose).buildClickEmbed());
        page3.put(Embed.ST_INFO_DPM_BTN_GET, embed.setDcm(dcmBtnClick).setDpm(dpmBtnClick).buildClickEmbed());

        lottery.put("page3", page3);
    }

    private Map<String, Object> buildFraudApiReq(HttpServletRequest request, ActivityOrderDto activityOrderDto,
                                                 String rid) {
        Map<String, Object> req = new HashMap<>();
        req.put("account_login", activityOrderDto.getConsumerId().toString());
        req.put("ip_address", RequestTool.getIpAddr(request));
        req.put("ext_media_id", activityOrderDto.getAppId().toString());
        req.put("ext_activity_id", activityOrderDto.getActivityId().toString());
        req.put("ext_requestid", rid);
        req.put("token_id", rid);
        req.put("ext_Advertising_id", activityOrderDto.getAdvertId().toString());
        req.put("event_occur_time", new DateTime(activityOrderDto.getGmtCreate().getTime()).toString("yyyy-MM-dd HH:mm:ss"));
        req.put("ext_Advertisingexposure_time", new DateTime().toString("yyyy-MM-dd HH:mm:ss"));
        req.put("slotId", RequestLocal.get().getSlotId());
        req.put("apiUrl", FraudApiRequest.API_URL);
        req.put("partner_code", FraudApiRequest.PARTNER_CODE);
        req.put("secret_key", FraudApiRequest.SECRET_KEY);
        req.put("event_id", FraudApiRequest.EVENT_ID);
        req.put("resp_detail_type", FraudApiRequest.RESP_DETAIL_TYPE);

        return req;
    }

    /**
     * 构造抽奖结果.
     *
     * @param lottery     the lottery
     * @param advert      the advert
     * @param showVersion 展示版本 false：旧弹层 ； true：新弹层
     * @throws ActivityException the activity exception
     */
    private void buildDoJoinRspForTuiaCoupon(HttpServletRequest request, Map<String, Object> lottery,
                                             ActivityOrderDto activityOrderDto, Long appId, Long consumerId,
                                             QueryAdvertRsp advert, Long activityId, Boolean showVersion)
            throws ActivityException {
        String activityOrderId = activityOrderDto.getOrderId();
        Integer activityType = activityOrderDto.getActivityType();
        String host = "//" + request.getHeader("host");
        String orderId = Constants.THE_PREFIX_ORDERID + activityOrderId;

        // 1.得到推啊券的标题和副标题
        lottery.put("tip", advert.getViceTitle());
        lottery.put("title", advert.getTitle());

        // 2.得到推啊券的马上使用按钮文案
        getButtonText(lottery, advert);

        int d = showVersion ? Constants.DPM.DPM_D_1 : Constants.DPM.DPM_D_0;

        // 3.马上使用&马上使用状态下的图片（曝光+访问）dpm=app_id.4.1.0;dcm=104.advertId.0.0
        String dpm = DpmInfo.getDpmInfo(appId, Constants.DPM.DPM_B_4, Constants.DPM.DPM_C_1, d);

        String styleType = request.getParameter("styleType");
        // 广告弹层id
        String skinId = this.getSkinId(request, activityId, activityType, advert.getAdvertId(), lottery);
        //3.6 特殊的广告id进行特殊弹层皮肤处理,当是AdvertLayerData中的广告并且分流50%时进行出行业定制弹层
        Long styleTypeLong = StringUtils.isNotBlank(styleType) ? Long.valueOf(styleType) : 0L;
        LayerSkinType layerSkinType = AdvertLayerData.getByAdvertId(advert.getAdvertId());
        if (layerSkinType != null && Objects.equals(StyleTypeUtil.half(styleTypeLong), 1L)) {
            LayerSkinDto layerSkinDto = this.skinService.selectSpecialLayer(layerSkinType.getType());
            if (layerSkinDto != null) {
                lottery.put("advertLayer", layerSkinDto);
                skinId=String.valueOf(layerSkinDto.getId());//特殊行业广告弹层时修改dcm
            }
        }
        //3.2广告券不同区域埋点信息dcm设置
        String dcm = DpmInfo.dcmClickInfo(Constants.DCM.DCM_A_104, advert.getAdvertId(), StringUtils.isBlank(skinId) ? "0" : skinId, advert.getMaterialId());

        String promoteUrl = EmbedUtil.getEncryptUrl(advert.getPromoteUrl(), consumerId);


        boolean showUse = false;
        lottery.put("link", getLink(host, activityOrderId, appId, dcm));

        //3.5
        String couponSource = CouponSource.ACTIVITY.getCode();

        if (ActivityType.isPlugin(activityType)) {
            couponSource = CouponSource.PLUGIN.getCode();
        }
        buildEmbed(request,lottery,consumerId,appId,d,activityOrderDto,advert,skinId,styleType,activityId,dpm,dcm);

        //3.5 返回广告id
        lottery.put("advertId", advert.getAdvertId());


        // 4.如果为可重复使用码或者普通优惠码
        if (advert.getCouponType() == 2 || advert.getCouponType() == 3) {

            // 4.1 如果为微信券
            if (advert.getIsWeixin() == 1) {

                showUse = true;
                lottery.put("useBtnText", "查看使用方法");
                promoteUrl = Constants.PATH.ACTIVITY + Constants.PATH.INDEX_RECORD
                        + "?vmName=detail&orderId=" + activityOrderId;
                dpm = DpmInfo.getDpmInfo(appId, Constants.DPM.DPM_B_4, Constants.DPM.DPM_C_2, d);
            }

            lottery.put("coupon_code", advert.getCodeContent());
            lottery.put("coupon_key", advert.getCodePasswd());
        }

        // 6.需要隐藏特殊网址
        showUse = getShowUse(appId, advert, promoteUrl, showUse);

        // 7.替换推啊域名
        promoteUrl = this.replaceLandDomain(promoteUrl, appId);

        // 5.1 跳转url组装并urlEncode
        promoteUrl = encodeUrl(promoteUrl);

        lottery.put("validate", advert.getEndValid());

        // 51信用卡不展示使用按钮
        if (appId == 16101) {
            showUse = false;
        }
        lottery.put("showUse", showUse);
        if (showUse) {
            lottery.put("openUrl", "");

            // 7.跳转web中间页
            promoteUrl = PathUtil.getButtonUrl(host, promoteUrl, activityOrderId, dcm, dpm, activityId, couponSource, styleType);

            lottery.put("iosDownloadUrl", promoteUrl);
            lottery.put("androidDownloadUrl", promoteUrl);
        }

        lottery.put(Constants.VALUENAME.IMG_URL, advert.getBannerPngUrl());

    }

    private void buildEmbed(HttpServletRequest request,Map<String, Object> lottery, Long consumerId,Long appId,int d,
                            ActivityOrderDto activityOrderDto,QueryAdvertRsp advert,String skinId,String styleType,
                            Long activityId,String dpm,String dcm) {

        //3.1广告券不同区域埋点信息
        String imgDpm = DpmInfo.getDpmInfo(appId, Constants.DPM.DPM_B_4, Constants.DPM.DPM_C_5, d);
        String btnGetDpm = DpmInfo.getDpmInfo(appId, Constants.DPM.DPM_B_4, Constants.DPM.DPM_C_6, d);
        String btnCloseDpm = DpmInfo.getDpmInfo(appId, Constants.DPM.DPM_B_4, Constants.DPM.DPM_C_4, d);
        String btnTitleDpm = DpmInfo.getDpmInfo(appId, Constants.DPM.DPM_B_4, Constants.DPM.DPM_C_7, d);
        String btnEncoreDpm = DpmInfo.getDpmInfo(appId, Constants.DPM.DPM_B_4, Constants.DPM.DPM_C_8, d);
        String dcmClick = DpmInfo.dcmClickInfo(Constants.DCM.DCM_A_104, advert.getAdvertId(), StringUtils.isBlank(skinId) ? "0" : skinId, advert.getMaterialId());
        //3.3dsm以及deliverType
        Integer deliverType = buildDeliverType();
        //3.4 获取dsm以及deliverType
        String dsm = buildDsm(activityOrderDto.getActivityId(), activityOrderDto.getActivityType(), request);
        //3.5
        String exposureEmbed = Embed.ST_INFO_DPM_EXPOSURE;
        String couponSource = CouponSource.ACTIVITY.getCode();
        String skinType = request.getParameter(Constants.VALUENAME.SKIN_TYPE);
        Integer activityType = activityOrderDto.getActivityType();

        if (ActivityType.isPlugin(activityOrderDto.getActivityType())) {
            deliverType = null;
            skinType = null;
            exposureEmbed = "st_info_dpm_img";
            couponSource = CouponSource.PLUGIN.getCode();
        }
        String host = "//" + request.getHeader("host");
        String orderId = Constants.THE_PREFIX_ORDERID + activityOrderDto.getOrderId();

        Long directPage = this.directPageSourceService.get(consumerId);
        lottery.put(exposureEmbed, DpmInfo.setStInfo(host, appId, consumerId, orderId,
                advert.getAdvertId(), advert.getMaterialId(), activityId, dpm,
                dcm, dsm, deliverType, skinType, couponSource, activityType, styleType, directPage));// 弹层图片埋点
        lottery.put("st_info_dpm_title_click", DpmInfo.setClickInfo(host, appId, consumerId, orderId,
                advert.getAdvertId(), advert.getMaterialId(), activityId, btnTitleDpm,
                dcmClick, dsm, deliverType, skinType, activityType, styleType, directPage));
        lottery.put(Embed.ST_INFO_DPM_BTN_GET, DpmInfo.setClickInfo(host, appId, consumerId, orderId,
                advert.getAdvertId(), advert.getMaterialId(), activityId, btnGetDpm,
                dcmClick, dsm, deliverType, skinType, activityType, styleType, directPage));
        lottery.put(Embed.ST_INFO_DPM_BTN_CLOSE, DpmInfo.setClickInfo(host, appId, consumerId, orderId,
                advert.getAdvertId(), advert.getMaterialId(), activityId, btnCloseDpm,
                dcmClick, dsm, deliverType, skinType, activityType, styleType, directPage));
        lottery.put("st_info_dpm_img_click", DpmInfo.setClickInfo(host, appId, consumerId, orderId,
                advert.getAdvertId(), advert.getMaterialId(), activityId, imgDpm,
                dcmClick, dsm, deliverType, skinType, activityType, styleType, directPage));
        lottery.put("st_info_dpm_btn_again", DpmInfo.setClickInfo(host, appId, consumerId, orderId,
                advert.getAdvertId(), advert.getMaterialId(), activityId, btnEncoreDpm,
                dcmClick, dsm, deliverType, skinType, activityType, styleType, directPage));
    }


    private String getSkinId(HttpServletRequest request, Long activityId, Integer activityType, Long advertId, Map<String, Object> lottery) {
        String skinId = request.getParameter("skinId");

        // 当广告id=24935 时，某些活动会 50%几率出定制弹层 //
        if (ActivityType.isActivity(activityType) && Long.valueOf(24935L).equals(advertId) && RandomUtils.nextBoolean()) {

            Integer specialSkinType = LayerSkinType.getCustomSkinType(activityId);
            if (specialSkinType != null) {

                LayerSkinDto layer = this.skinService.selectSpecialLayer(specialSkinType);
                if (layer != null) {
                    skinId = String.valueOf(layer.getId());
                    lottery.put("layerSkinType", layer.getSkinType());
                }
            }

        }

        // skinId 为空时，填0
        if (StringUtils.isBlank(skinId)) {
            skinId = "0";
        }
        return skinId;
    }

    /**
     * 落地页去除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("https:", "").replace("http:", "");
            }
        }

        return promoteUrl;
    }

    private String encodeUrl(String url) throws ActivityException {
        String promoteUrl;
        try {
            promoteUrl = URLEncoder.encode(url.trim(), "utf-8");
        } catch (UnsupportedEncodingException e) {

            throw new ActivityException(e);

        }
        return promoteUrl;
    }

    private void getButtonText(Map<String, Object> lottery, QueryAdvertRsp advert) {
        if (StringUtils.isBlank(advert.getButtonText())) {
            lottery.put("useBtnText", "马上使用");
        } else {
            lottery.put("useBtnText", advert.getButtonText());
        }
    }

    private boolean getShowUse(Long appId, QueryAdvertRsp advert, String promoteUrl, boolean showUse) {
        if (advert.getSpecialHide() == 1) {

            // 6.1如果为普通券和可重复使用券并且为微信券， 则展示
            if ((advert.getCouponType() == 2 || advert.getCouponType() == 3) && advert.getIsWeixin() == 1) {
                showUse = true;

            } else if (advert.getCouponType() != 1) {
                // 6.2如果为普通券和可重复使用券并且但不为微信券

                if (AppIdConstant.showUseButton.contains(appId)) {
                    showUse = false;
                } else {
                    showUse = true;
                }
            }

        } else if (StringUtils.isNotBlank(promoteUrl)) {
            // 6.3如果推广网址不为空， 则展示
            showUse = true;
        }
        return showUse;
    }

    /**
     * Gets the link.
     *
     * @param appId the app id
     * @param dcm the dcm
     * @return the link
     */
    private String getLink(String host, String orderId, Long appId, String dcm) {
        StringBuilder builder = new StringBuilder();
        builder.append(host).append(Constants.PATH.ACTIVITY).append(Constants.PATH.INDEX_RECORD).append("?vmName=detail&orderId=").append(orderId);
        builder.append("&dpm=");
        builder.append(DpmInfo.getDpmInfo(appId, Constants.DPM.DPM_B_4, Constants.DPM.DPM_C_3,
                Constants.DPM.DPM_D_0));
        builder.append("&dcm=");
        builder.append(dcm);

        return builder.toString();

    }


    private String buildDsm(Long id, Integer activityType, HttpServletRequest request) {
        String type = ActivityType.isPlugin(activityType) ? Constants.COOKIEKEY.PLUGIN : Constants.COOKIEKEY.ACT;
        //获取cookie中的dsm
        DmCookieHolder dmCookie = CookieUtil.getDmCookie(type, id.toString());
        String dsm = null;
        if(dmCookie!=null){
            dsm = dmCookie.getDsm();
        }
        //如果cookie中取不到
        if (StringUtils.isBlank(dsm)) {
            String url = request.getHeader("referer");
            Map<String, String> requestMap = PathUtil.analysisURLRequest(url);
            dsm = requestMap.get("dsm");
        }
        return dsm;

    }

    private Integer buildDeliverType() {
        return DeliveryType.ACTIVITY.getType();
    }

}
