package com.duiba.tuia.youtui.web.controller;

import cn.com.duiba.tuia.activity.center.api.constant.LoginType;
import cn.com.duiba.tuia.activity.center.api.dto.consumer.ConsumerCache;
import cn.com.duiba.wolf.utils.UrlUtils;
import cn.com.duibaboot.ext.autoconfigure.accesslog.AccessLogFilter;
import com.alibaba.fastjson.JSONObject;
import com.dianping.cat.Cat;
import com.duiba.tuia.youtui.web.bo.ActivityBO;
import com.duiba.tuia.youtui.web.bo.AdvertBO;
import com.duiba.tuia.youtui.web.bo.MainMeetBO;
import com.duiba.tuia.youtui.web.constant.Constants;
import com.duiba.tuia.youtui.web.constant.ErrorCode;
import com.duiba.tuia.youtui.web.exception.ActivityException;
import com.duiba.tuia.youtui.web.model.Result;
import com.duiba.tuia.youtui.web.model.UserAccount;
import com.duiba.tuia.youtui.web.model.req.DirectPageReq;
import com.duiba.tuia.youtui.web.model.req.IndexReq;
import com.duiba.tuia.youtui.web.model.req.WebShowClickLogReq;
import com.duiba.tuia.youtui.web.model.rsp.DirectBlockRsp;
import com.duiba.tuia.youtui.web.model.rsp.DirectPageRsp;
import com.duiba.tuia.youtui.web.model.rsp.GameHallAnnouncementRsp;
import com.duiba.tuia.youtui.web.service.AdvertService;
import com.duiba.tuia.youtui.web.service.CommonService;
import com.duiba.tuia.youtui.web.service.ConsumerService;
import com.duiba.tuia.youtui.web.service.SystemConfigService;
import com.duiba.tuia.youtui.web.service.UserBalanceService;
import com.duiba.tuia.youtui.web.tool.DomainConstantUtil;
import com.duiba.tuia.youtui.web.tool.Environment;
import com.duiba.tuia.youtui.web.tool.PathUtil;
import com.duiba.tuia.youtui.web.tool.QpsLimit;
import com.duiba.tuia.youtui.web.tool.RequestLocal;
import com.duiba.tuia.youtui.web.tool.RequestTool;
import com.google.common.collect.Maps;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringEscapeUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.util.Map;

/**
 * 直投页
 * 需求：http://cf.dui88.com/pages/viewpage.action?pageId=5528200
 * 技术方案：http://cf.dui88.com/pages/viewpage.action?pageId=5531210
 */
@Controller
@RequestMapping("/direct")
@Api("直投变现页API")
public class DirectPageController extends BaseController implements InitializingBean{
    @Autowired
    MainMeetBO mainMeetBO;

    @Autowired
    AdvertBO advertBO;

    @Autowired
    ActivityBO activityBO;

    @Autowired
    private CommonService commonService;
    @Autowired
    private AdvertService advertService;

    @Autowired
    private UserBalanceService userBalanceService;

    @Autowired
    private SystemConfigService systemConfigService;

    @Autowired
    private ConsumerService consumerService;

    private int limitTimes = 24;

    @Override
    public void afterPropertiesSet() throws Exception {
        if (Environment.isOnline()) {
            limitTimes /= Constants.SERVER_NUM;
        }
    }

    @RequestMapping(value = "/index", method = RequestMethod.GET)
    public ModelAndView index(@ModelAttribute IndexReq req, HttpServletRequest request) throws ActivityException {
        // 1.获取用户信息
        UserAccount consumer = RequestLocal.get().getUserAccount();
        if (null == consumer || null == req.getId()) {
            return new ModelAndView(Constants.MODEL_ERROR);
        }

        if (!QpsLimit.builder().isQpmLimit(this.generatorKey(consumer.getUserId()), limitTimes)) {
            return new ModelAndView(Constants.MODEL_ERROR);
        }

        try {
            Cat.logMetricForCount("活动中心-直投页访问");
        } catch (Exception e) {
            logger.error(Constants.CAT_ERROR, e);
        }
        try {
            req.setHost(request.getHeader("host"));
            AccessLogFilter.putExPair("use_host",request.getHeader("host"));
            AccessLogFilter.putExPair("agreement",request.getHeader("X-Forwarded-Proto")==null?"http":request.getHeader("X-Forwarded-Proto"));
            return mainMeetBO.index(request, req, consumer);
        } catch (Exception e) {
            logger.warn("初始化直投变现页失败，请检查ID :" + req.getId(), e);
            return new ModelAndView(Constants.MODEL_ERROR);
        }

    }

    private String generatorKey(Long consumerId) {
        return "direct" + consumerId;
    }

    /**
     * 直投页获取广告接口
     * @param req req
     * @param request 请求
     * @param response 返回
     * @return DirectPageRsp
     */
    @RequestMapping(value="/getWubo")
    @ResponseBody
    public Result<DirectPageRsp> getAdvert(@RequestBody DirectPageReq req, HttpServletRequest request, HttpServletResponse response) {
        try {
            setParam(req,request);
            return super.successResult(this.mainMeetBO.getAdvert(request, req));
        } catch (Exception e) {
            return super.failResult(e);
        }
    }

    /**
     * 直投页获取区块接口
     * @param request
     * @return
     */
    @RequestMapping(value="/getBlock")
    @ResponseBody
    public Result<DirectBlockRsp> getBlock(DirectPageReq req,HttpServletRequest request) {
        try{
            setParam(req, request);
            if (null == req.getSlotId()) {
                throw new ActivityException(ErrorCode.E0000001);
            }
            return super.successResult(this.mainMeetBO.getDirectBlock(request,req,false));
        } catch (Exception e){
            logger.error("",e);
            return super.failResult(e);
        }
    }

    /**
     * 直投页获取区块接口
     * 广告过滤接口使用1期接口
     */
    @RequestMapping(value="/getAdpages")
    @ResponseBody
    public Result<DirectBlockRsp> getAdvert(DirectPageReq req, HttpServletRequest request) {
        try{
            setParam(req, request);
            if (null == req.getSlotId()) {
                throw new ActivityException(ErrorCode.E0000001);
            }
            return super.successResult(this.mainMeetBO.getDirectBlock(request,req,true));
        } catch (Exception e){
            logger.error("",e);
            return super.failResult(e);
        }
    }

    /**
     * 获取直投页区块信息
     * @param req
     * @param request
     * @return
     */
    @RequestMapping(value="/getDengqin")
    @ResponseBody
    public Result<DirectBlockRsp> getAdvert3(DirectPageReq req, HttpServletRequest request) {
        try {
            setParam(req, request);
            if (null == req.getSlotId()) {
                throw new ActivityException(ErrorCode.E0000001);
            }
            // 将流量来源放入logMap中
            if (StringUtils.isNotBlank(req.getAppFlowType())) {
                req.getParamMap().put("appFlowType", req.getAppFlowType());
            }
            return super.successResult(this.mainMeetBO.getDirectBlockNew(request, req));
        } catch (Exception e) {
            logger.error("", e);
            return super.failResult(e);
        }
    }

    private void setParam(DirectPageReq req, HttpServletRequest request) throws ActivityException {
        RequestLocal local = RequestLocal.get();
        // 参数校验
        if(null == local || null == local.getAppId() || null == local.getCid()
                || StringUtils.isBlank(RequestTool.getIpAddr(request)) || StringUtils.isBlank(RequestTool.getUserAgent(request))){
            throw new ActivityException(ErrorCode.E0200002);
        }
        req.setAppId(local.getAppId());
        req.setConsumerId(local.getCid());
        req.setDeviceId(local.getDeviceId());
        req.setHost(request.getHeader("host"));
        req.setIp(RequestTool.getIpAddr(request));
        req.setOs(RequestTool.getOSNew(request));
        req.setUserAgent(RequestTool.getUserAgent(request));
        req.setReferer(request.getHeader(Constants.HTTPHEADER.REFERER));
        String slotId = local.getSlotIdByAppId(req.getAppId());
        if (StringUtils.isNotBlank(slotId)) {
            req.setSlotId(Long.parseLong(slotId));
        }
        req.setParamMap(local.getCollParams());
        if (LoginType.PREVIEW.equalsCode(req.getLogin())) {//针对预览处理
            req.setSlotId(0L);
        }

    }

    @RequestMapping(value = "/getTimes", method = {RequestMethod.GET})
    @ResponseBody
    public Result<String> getTimes(HttpServletRequest request, Long id) {
        return super.successResult(this.advertService.getAdvertTimes(id));
    }

    @RequestMapping(value = "/redirect", method = {RequestMethod.GET, RequestMethod.POST})
    public void redirect(@ModelAttribute WebShowClickLogReq req, HttpServletRequest request,
                         HttpServletResponse response) {
        try {

            String orderId;//订单
            String cid = String.valueOf(RequestLocal.get().getCid());//用户id
            String slotIdStr = RequestLocal.get().getSlotId();//广告位 id，优先从cookie获取，没有的话从参数中获取
            if (StringUtils.isBlank(slotIdStr)) {
                slotIdStr = String.valueOf(req.getSlotId());
            } else {
                req.setSlotId(Long.parseLong(slotIdStr));
            }

            req.setDeviceId(RequestLocal.get().getDeviceId());//设备id

            Map<String,String> urlParams = Maps.newHashMap();
            String url = StringEscapeUtils.unescapeHtml3(req.getUrl());
            if (req.getAdvertId() != null) {//直投页 有广告id  拼链接
                this.advertBO.directAdvertLog(req, request);

                //落地页 需要的参数
                urlParams.put("a_advertId", String.valueOf(req.getAdvertId()));
                orderId = req.getOrderId();

            } else { //直投页 无广告，前端写死链接的
                orderId = this.commonService.getNextOrderId(Constants.THE_PREFIX_LINK);
            }
            urlParams.put("a_deliveryType", "2");//2表示来源直投页
            urlParams.put("a_slotId", slotIdStr);

            setPageId(req, request, urlParams);
            url = UrlUtils.appendParams(this.activityBO.urlFilter(request, url, orderId, cid), urlParams);
            if (url.contains(DomainConstantUtil.getYoutuiDomain())) {
                url = url.replaceFirst(DomainConstantUtil.getYoutuiDomain(), request.getHeader("host"));
            }
            response.sendRedirect(PathUtil.processActivityUrl(url, request));
        } catch (Exception e) {
            super.failResult(e);
        }
    }

    private void setPageId(WebShowClickLogReq req, HttpServletRequest request,Map<String,String> params) {
        // 直投页落地页日志记录 pageId
        // 先从参数中获取，如果 获取不到，则从refer中获取。
        try {
            Long pageId = req.getPageId();
            if (pageId == null) {
                params.put("a_pageId", RequestTool.getParamFromReferer(request, "id"));
            } else {
                params.put("a_pageId", String.valueOf(pageId));
            }
        } catch (Exception e) {
            logger.warn("直投页获取pageId异常");
        }
    }

    @ResponseBody
    @RequestMapping(value = "/getWalletEmbed", method = {RequestMethod.GET})
    @ApiOperation(value = "getWalletEmbed", httpMethod = "GET", notes = "获取现金钱包直投页定制埋点接口")
    public Result<Map<String, String>> getWalletEmbed(@Valid Long pageId,String dsm, HttpServletRequest request, HttpServletResponse response) {
        try {
            Long appId = RequestLocal.get().getAppId();
            Long userId = RequestLocal.get().getCid();
            String host = request.getHeader("host");
            return successResult(mainMeetBO.buildWalletEmbed(dsm,appId,pageId,userId,host));
        } catch (Exception e) {
            return failResult(e);
        }
    }

    @ResponseBody
    @RequestMapping(value = "/getGameHallEmbed", method = {RequestMethod.GET})
    @ApiOperation(value = "getGameHallEmbed", httpMethod = "GET", notes = "获取游戏大厅定制埋点接口")
    public Result<Map<String, String>> getGameHallEmbed(@Valid Long pageId, String dsm, HttpServletRequest request, HttpServletResponse response) {
        try {
            Long appId = RequestLocal.get().getAppId();
            Long userId = RequestLocal.get().getCid();
            String host = request.getHeader("host");
            return successResult(mainMeetBO.buildGameHallEmbed(dsm, appId, userId, host));
        } catch (Exception e) {
            return failResult(e);
        }
    }


    @ResponseBody
    @RequestMapping(value = "/getNewGameHallEmbed", method = {RequestMethod.GET})
    @ApiOperation(value = "getNewGameHallEmbed", httpMethod = "GET", notes = "获取游戏大厅定制埋点接口")
    public Result<JSONObject> getNewGameHallEmbed(@Valid Long pageId, String dsm, HttpServletRequest request, HttpServletResponse response) {
        try {
            Long appId = RequestLocal.get().getAppId();
            Long userId = RequestLocal.get().getCid();
            String host = request.getHeader("host");
            return successResult(mainMeetBO.buildNewGameHallEmbed(dsm, appId, userId, host, pageId));
        } catch (Exception e) {
            return failResult(e);
        }
    }

    @ResponseBody
    @RequestMapping(value = "/getAnnouncement", method = {RequestMethod.GET})
    @ApiOperation(value = "getAnnouncement", httpMethod = "GET", notes = "获取游戏大厅公告")
    public Result<Map<String,GameHallAnnouncementRsp>> getAnnouncement() {
        try {
            return successResult(mainMeetBO.getAnnouncement());
        } catch (Exception e) {
            return failResult(e);
        }
    }

    @ResponseBody
    @RequestMapping(value = "/getDuibaUrl", method = {RequestMethod.GET})
    @ApiOperation(value = "getDuibaUrl", httpMethod = "GET", notes = "获取积分商城免登链接")
    public Result<String> getDuibaUrl(Integer balanceType, HttpServletRequest request, HttpServletResponse response) {
        try {
            UserAccount user = RequestLocal.get().getUserAccount();
            if(null == user || null == user.getUserId() || !RequestLocal.get().getLoginStatus()){
                throw new ActivityException(ErrorCode.E0200002.geteCode() ,"用户不存在或未登录");
            }
            Long userId = user.getUserId();
            Long appId = user.getAppId();
            ConsumerCache consumerCache = consumerService.getConsumerCache(userId);
            Long credits = userBalanceService.getAmount(userId, balanceType);
            if(null == credits || null == consumerCache){
                throw new ActivityException(ErrorCode.E0200017.geteCode() ,"账户不正确");
            }

            String redirectUrl = systemConfigService.getSystemConfig("tuia_credits_redirect_url");

            return successResult(PathUtil.buildAutoLoginRequest(userId.toString(), credits, appId + "_" + RequestLocal.get().getSlotIdByAppId(appId), redirectUrl, consumerCache));

        } catch (Exception e) {
            return failResult(e);
        }
    }
}
