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

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;

import java.util.Calendar;
import java.util.Date;
import java.util.Enumeration;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.Pattern;

import org.apache.commons.lang.StringEscapeUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.ModelAndView;

import cn.com.duiba.tuia.activity.center.api.dto.LandUserInfoDto;
import cn.com.duiba.tuia.activity.center.api.dto.rsp.AlipayCmapRsp;
import cn.com.duiba.wolf.perf.timeprofile.RequestTool;
import cn.com.duiba.wolf.utils.BeanUtils;
import cn.com.duiba.wolf.utils.DateUtils;
import cn.com.duibaboot.ext.autoconfigure.accesslog.AccessLogFilter;

import com.alibaba.fastjson.JSONObject;
import com.duiba.tuia.youtui.web.biz.land.param.LandExtendParam;
import com.duiba.tuia.youtui.web.biz.land.param.LandParamI;
import com.duiba.tuia.youtui.web.constant.Constants;
import com.duiba.tuia.youtui.web.constant.ErrorCode;
import com.duiba.tuia.youtui.web.constant.InsuranceMsgEnum;
import com.duiba.tuia.youtui.web.constant.LandChannel;
import com.duiba.tuia.youtui.web.constant.TaoBaoCode;
import com.duiba.tuia.youtui.web.exception.ActivityException;
import com.duiba.tuia.youtui.web.exception.ActivityRuntimeException;
import com.duiba.tuia.youtui.web.exception.InsuranceException;
import com.duiba.tuia.youtui.web.log.InnerLogService;
import com.duiba.tuia.youtui.web.model.Result;
import com.duiba.tuia.youtui.web.model.req.LandUserFormInfo;
import com.duiba.tuia.youtui.web.model.req.LandUserInfo;
import com.duiba.tuia.youtui.web.model.rsp.InsuranceResultRsp;
import com.duiba.tuia.youtui.web.model.rsp.LandRsp;
import com.duiba.tuia.youtui.web.service.CommonService;
import com.duiba.tuia.youtui.web.service.InterfaceService;
import com.duiba.tuia.youtui.web.service.LandService;
import com.duiba.tuia.youtui.web.service.LocalCacheService;
import com.duiba.tuia.youtui.web.service.SmsService;
import com.duiba.tuia.youtui.web.tool.RequestLocal;
import com.duiba.tuia.youtui.web.tool.ResultUtil;
import com.duiba.tuia.youtui.web.tool.UrlBase64;
import com.google.common.collect.Maps;

/**
 * ClassName: LandController <br/>
 * Function: 落地页Controller. <br/>
 * Reason: . <br/>
 * date: 2017年4月24日 上午10:27:53 <br/>
 *
 * @author wubo
 * @version 
 * @since JDK 1.7
 */
@RestController
@RequestMapping("/land")
@Api("落地页")
public class LandController extends BaseController {
	
	private static final Logger log = LoggerFactory.getLogger(LandController.class);
	
	private static final int LAND_GROUP = 3; //  inner 日志group
	private static final int LAND_TYPE = 1;

	private static final int MIN_UNENCODE_LAND_ID = 400;//最小的未加密的落地页id
	
	@Autowired
	private LandService landService;
	
	@Autowired
	private LocalCacheService localCacheService;
	
	@Autowired
	private SmsService smsService;
	
	@Autowired
	private InterfaceService interfaceService;

	@Autowired
	private CommonService commonService;
	
    /**
     * landService:(通用接口). <br/>
     * 
     * @param request
     * @return json
     */
    @RequestMapping("service")
    @ResponseBody
    public Object landService(HttpServletRequest request) {
        try {
            String code = this.getInterfaceCode(request);
            Map<String, Object> params = Maps.newHashMap();

            Enumeration<String> ps = request.getParameterNames();
            while (ps.hasMoreElements()) {
                String name = ps.nextElement();
                params.put(name, request.getParameter(name));
            }
			return this.interfaceService.invoke(code, params);
        } catch (Exception e) {
            return super.failResult(e);
        }
    }
	
    /**
     * saveInfo:(保险落地页保存接口). <br/>
     * 返回跳转的url
     * 
     * @return json
     */
    @RequestMapping("/saveInfo")
    @ResponseBody
    public Object saveInfo(LandUserInfo landUserInfo,  HttpServletRequest request, HttpServletResponse response) {
        try {

            String interfaceCode = this.getInterfaceCode(request);

            // inner log
            innerUserLog(landUserInfo);

            Long appId = RequestLocal.get().getAppId();
            Long cid = RequestLocal.get().getCid();
            LandExtendParam extendParam = new LandExtendParam();
            extendParam.setConsumerId(cid);
            extendParam.setAppId(appId);
            extendParam.setInterfaceCode(interfaceCode);
            extendParam.setSubchannel(request.getParameter(Constants.VALUENAME.SUB_CHANNEL));
            
            // 落地业务s
            InsuranceResultRsp rsp = this.landService.insurancePage(landUserInfo, extendParam);

            return successResult(rsp);
        } catch (Exception e) {
            log.warn("保险落地页投保失败", e);
            return ResultUtil.fail(ErrorCode.E9999999.geteCode(), e.getMessage());
        }
    }

	/**
	 * 保险落地页用户信息更新接口
	 * @param landUserInfo
	 * @param request
	 * @return json
	 */
	@RequestMapping("/updateInfo")
	@ResponseBody
	public Object updateInfo(LandUserInfo landUserInfo,  HttpServletRequest request) {
    	try {
    	    if(landUserInfo == null||landUserInfo.getChannel() == null){
    	        return ResultUtil.fail(ErrorCode.E0000001.geteCode(),"uid,userId,Channel必填");
    	    }
    	    
    	    String code = request.getParameter("code");
    	    this.landService.updateUserInfo(landUserInfo,code);
			return successResult("ok");
		} catch (Exception e) {
			log.warn("保险落地页用户信息更新失败", e);
			return ResultUtil.fail(ErrorCode.E9999999.geteCode(), e.getMessage());
		}
	}

	/**
	 * 保险落地页 保存用户信息并跳到结果页
	 * @param landUserInfo
	 * @param response
	 * @param request
	 * @return View
	 */
    @RequestMapping("/resultPage")
    @ResponseBody
    public ModelAndView saveToResultPage(LandUserInfo landUserInfo, HttpServletResponse response,
                                         HttpServletRequest request) {

        ModelAndView model = new ModelAndView("land/result");// 结果页
        Map<String, String> responseMap = Maps.newHashMap();// 返回参数

        try {
            landUserInfo.checkParams();
            String interfaceCode = this.getInterfaceCode(request);
            Long landId = landUserInfo.getLandId();

            innerUserLog(landUserInfo);

            // 返回页面的参数
            model.addObject("equity", true);
            responseMap.put("id", String.valueOf(landId));

            Long appId = RequestLocal.get().getAppId();
            Long cid = RequestLocal.get().getCid();
            LandExtendParam extendParam = new LandExtendParam();
            extendParam.setConsumerId(cid);
            extendParam.setAppId(appId);
            extendParam.setInterfaceCode(interfaceCode);
            extendParam.setSubchannel(request.getParameter("subchannel"));
            InsuranceResultRsp rsp;

            model.addAllObjects(responseMap);
            try {
                rsp = this.landService.insurancePage(landUserInfo, extendParam);
            } catch (Exception e) {
                log.error("黑牛接口异常,error:", e);
                throw new InsuranceException(InsuranceMsgEnum.M006001);
            }

            String status = rsp.getStatus();
            if (!"0".equals(status)) {// 状态不为0的表示投保失败,错误提示用统一的006003文案
                throw new InsuranceException(true, status, InsuranceMsgEnum.M006003);
            }

            model = result(model, true, "0", InsuranceMsgEnum.M006002.getMessage(rsp.getPolicyName()),
                           InsuranceMsgEnum.M006002.getTip(rsp.getCompanyName()));
        } catch (InsuranceException e) {
            model = result(model, e.getSuccess(), e.getStatus(), e.getMessage(), e.getTip());
        } catch (Exception e) {
            log.error("", e);
            model = new ModelAndView(Constants.MODEL_ERROR);
        }

		model.addObject("pageHost", "//" + request.getHeader("host"));
        return model;
    }

    private ModelAndView result(ModelAndView model, boolean success, String status, String message, String tip) {
        model.addObject("success", success);
        model.addObject("message", message);
        model.addObject("tip", tip);
        model.addObject("status", status);
        return model;
    }
	/**
	 * 获取页面信息
	 * @param id
	 * @return
	 */
	@RequestMapping("/landPage")
	@ResponseBody
	@ApiOperation(value = "落地页查询", notes = "落地页查询", httpMethod="GET")
    @ApiImplicitParam(name = "id", required = true, value = "落地页id", dataType = "String", paramType = "query") 
	public ModelAndView landPage(@RequestParam(name = "id") String id, HttpServletRequest request) {
	    
	    Long landPageId = getLandPageId(id);
	    try{
	        LandRsp landRsp = localCacheService.getValueIn5Min(landPageId);
	        ModelAndView model;
	        if (landRsp.getLandType() == 1) {
	            model = new ModelAndView("land/landPageTemplate");
            }else{
                model = new ModelAndView("land/index");
                model.addObject("html", landRsp.getHtml());
            }
			model.addObject("pageHost", "//" + request.getHeader("host"));
			AccessLogFilter.putExPair("use_host",request.getHeader("host"));
	        return model;

	    }catch(Exception e){
	    	log.warn("LandController->landPage", e);
	        return new ModelAndView(Constants.MODEL_ERROR);
	    }
	}
	
	/**
	 * 获取落地页详情信息
	 * @param id
	 * @return
	 */
	@RequestMapping("/landPageDetail")
	@ResponseBody
	@ApiOperation(value = "获取落地页详情信息", notes = "获取落地页详情信息", httpMethod="GET", response = LandRsp.class)
    @ApiImplicitParam(name = "id", required = true, value = "落地页id", dataType = "String", paramType = "query") 
	public Result<LandRsp> landPageDetail(@RequestParam(name = "id") String id, HttpServletRequest request) {
	    Long landPageId = getLandPageId(id);
	    
	    try{
	        return successResult(localCacheService.getValueIn5Min(landPageId));
	    }catch(Exception e){
	        log.warn("LandController->landPageDetail", e);
	        return failResult(e);
	    }
	}

	private Long getLandPageId(String id) {
	    Long landPageId;
	    try {
            landPageId  = Long.parseLong(id);
            // 3.22上线后，id大于400的新建落地页，链接复制时id已加密。如果id未加密，则为别人尝试
            if (landPageId >= MIN_UNENCODE_LAND_ID) {
                throw new ActivityRuntimeException("参数不正确"); 
            }
        } catch (NumberFormatException e) {
            String landPageIdStr = UrlBase64.urlBase64Decode(id);
            if (StringUtils.isEmpty(landPageIdStr)) {
                throw new ActivityRuntimeException("参数不正确");
            }
            landPageId  = Long.parseLong(landPageIdStr);
        }
        if (landPageId <= 0) {
            log.warn("landPage req id is incorrect ");
            throw new ActivityRuntimeException("参数不正确");
        }
        return landPageId;
    }

    /**
	 * 落地页日志接口
	 * @param landId
	 * @param landSubId
	 * @param request
	 * @return
	 */
	@RequestMapping("/landPageLog")
	public Object landPageLog(Long landId,
			@RequestParam(value="landSubId",required=false) String landSubId, 
			HttpServletRequest request){
		if(landId == null){
			throw new ActivityRuntimeException("页面id为空");
		}
		Long appId = RequestLocal.get().getAppId();
		Long cid = RequestLocal.get().getCid();
		String ip = RequestTool.getIpAddr(request);
		JSONObject json = new JSONObject();
		json.put("htmlId", landId);
		json.put("consumer_id", cid);
		json.put("appId", appId);
		String ua = request.getHeader("User-Agent");
		if (StringUtils.isNotBlank(ua) && ua.length() > 500) {
            ua = ua.substring(0, 499);
        }
		json.put("ua", ua);
		json.put("ip", ip);
		if(landSubId != null){
			json.put("landSubId", landSubId);
		}
		InnerLogService.landPageLog(LAND_GROUP, LAND_TYPE, json);
		return successResult();
	}

	/**
	 * 落地页提交信息接口
	 * @param landUserInfo
	 * @param request
	 * @param response
	 * @return
	 */
	@RequestMapping("/submit")
	public Object submit(LandUserInfo landUserInfo,
			HttpServletRequest request,HttpServletResponse response){
		try {
			Long appId = RequestLocal.get().getAppId();
			Long cid = RequestLocal.get().getCid();

			Long landId = landUserInfo.getLandId();
			if (landId == null) {
				throw new ActivityRuntimeException("内容不存在");
			}
			innerUserLog(landUserInfo);

			LandExtendParam extendParam = new LandExtendParam();
			extendParam.setAppId(appId);
			extendParam.setConsumerId(cid);
			extendParam.setSmsCode(request.getParameter("smsCode"));
			//1.业务处理
			landService.LandingPage(landUserInfo, extendParam, response);
			//2.日志记录
			submitLog(appId, cid, landUserInfo, request);
			Map<String,Object> resp = Maps.newHashMap();
			resp.put("orderId", landUserInfo.getOrderId());
			return successResult(resp);
		} catch (ActivityException e) {
			return failResult(e);
		}
	}
	
	    @ResponseBody
	    @ApiOperation(value = "模板落地页提交表单", notes = "模板落地页提交表单", httpMethod="POST")
	    @RequestMapping(value = "/submitForm", method = RequestMethod.POST)
	    public Object submitForm(LandUserFormInfo landUserInfo,
	            HttpServletRequest request,HttpServletResponse response){
	        try {

	            Long landId = landUserInfo.getLandId();
	            if (landId == null) {
	                throw new ActivityRuntimeException("内容不存在");
	            }
	            // 省市区分隔
	            if (StringUtils.isNotBlank(landUserInfo.getLocation())) {
	                String[] location = landUserInfo.getLocation().split(LandUserFormInfo.SPLIT_LOCATION);
	                if (location.length > 0) {
	                    landUserInfo.setProvince(location[0]);
	                }
	                if (location.length > 1) {
	                    landUserInfo.setCity(location[1]);
	                }
	                if (location.length > 2) {
	                    landUserInfo.setRegion(location[2]);
	                }
	            }
	            
	            LandExtendParam extendParam = new LandExtendParam();
	            extendParam.setAppId(RequestLocal.get().getAppId());
	            extendParam.setConsumerId(RequestLocal.get().getCid());
	            LandUserInfo user = BeanUtils.copy(landUserInfo, LandUserInfo.class);
	            user.setInfo(StringEscapeUtils.unescapeHtml(landUserInfo.getListUserInfo()));
	            // 内部日志
	            innerUserLog(user);
	            // 保存
	            landService.submitForm(landUserInfo, extendParam);
	            // 用户信息提交日志打印
	            submitLog(RequestLocal.get().getAppId(), RequestLocal.get().getCid(), user, request);
	            Map<String,Object> resp = Maps.newHashMap();
	            return successResult(resp);
	        } catch (ActivityException e) {
	            return failResult(e);
	        }
	    }
	/**
	 * 落地页发送信息接口
	 * @param phone
	 * @param landId
	 * @param landSubId
	 * @param channel
	 * @param request
	 * @return
	 */
	@RequestMapping("/sendCode")
	public Object sendCode(String phone, Long landId, String landSubId, String channel, HttpServletRequest request){
		if(!StringUtils.isNumeric(phone)){
			throw new ActivityRuntimeException("手机号不合法");
		}
		if(landId == null || channel == null){
			throw new ActivityRuntimeException("内容不存在");
		}
		try {
			if (LandChannel.SJD_CHANNEL.equals(channel) && landService.isExist(phone, landId)) {
				throw new ActivityException(ErrorCode.E0100006);
			}
			smsService.send(phone, channel);
			//日志打印
			sendCodeLog(phone, landId, landSubId, request);
		} catch (ActivityException e) {
			return failResult(e);
		}
		return successResult();
	}
	
	@RequestMapping("/codeVerify")
	public Object codeVerify(String phone,String channel,String smsCode){
	    try{
	        if(StringUtils.isAnyBlank(phone,channel,smsCode)){
	            throw new ActivityException(ErrorCode.E0000001);
	        }
	        if(!this.smsService.verify(phone, smsCode, channel)){
	            throw new ActivityException(ErrorCode.E0100004);
	        }
	        return successResult();
	        
	    } catch (ActivityException e) {
	        logger.info("",e);
	        return failResult(e);
	    }
	}
	
	@RequestMapping("/getRequestParam")
	public Object getRequestParam(String phone, String code, String landSubId, String channel, Long landId, 
			HttpServletRequest request,HttpServletResponse response){
		if(StringUtils.isAnyBlank(code,channel)){
			return failResult(new ActivityException(ErrorCode.E0000001));
		}
		if(landId == null){
			return failResult(new ActivityException(ErrorCode.E0100007));
		}
		if(!StringUtils.isNumeric(phone)){
			return failResult(new ActivityException(ErrorCode.E0000001));
		}
		
		boolean success = smsService.verify(phone, code, channel);
		if(!success){
			return failResult(new ActivityException(ErrorCode.E0100004));
		}
		
		LandUserInfo info = new LandUserInfo();
		info.setChannel(channel);
		info.setLandId(landId);
		info.setLandSubId(landSubId);
		info.setUserPhone(phone);
		submit(info, request, response);
		
		 LandParamI param = landService.getParam(info);
		 if(param == null){
			 return failResult(new ActivityException(ErrorCode.E0000001));
		 }
		
		return successResult(param.getRequestParam(info));
	}

	@RequestMapping("/order")
	public Object getOrder(HttpServletRequest request) {
		return successResult(this.commonService.getNextOrderId(""));
	}

	@RequestMapping("/getCode")
	public Object getCode(String tuiaId,HttpServletRequest request) {
		return successResult(TaoBaoCode.getCode(RequestLocal.get().getAppId(),tuiaId));
	}

	/**
	 * 用户信息提交日志打印
	 * @param appId
	 * @param cid
	 * @param landUserInfo
	 * @param request
	 */
	private void submitLog(Long appId, Long cid, LandUserInfo landUserInfo, HttpServletRequest request) {

		String ip = RequestTool.getIpAddr(request);
		JSONObject json = new JSONObject();
		json.put("htmlId", landUserInfo.getLandId());
		json.put("consumer_id", cid);
		json.put("appId", appId);
		String ua = request.getHeader("User-Agent");
		if (StringUtils.isNotBlank(ua) && ua.length() > 500) {
			ua = ua.substring(0, 499);
		}
		json.put("ua", ua);
		json.put("ip", ip);
		json.put("phone", landUserInfo.getUserPhone());
		if (landUserInfo.getUserName() != null) {
			json.put("user_name", landUserInfo.getUserName());
		}
		if (landUserInfo.getLandSubId() != null) {
			json.put("landSubId", landUserInfo.getLandSubId());
		}
		InnerLogService.landPageLog(LAND_GROUP, LAND_TYPE, json);
	}
	
	/**
	 * 验证码发送日志打印.
	 *
	 * @param phone 手机号
	 * @param landId 落地页id
	 * @param landSubId 验证码发送按钮id
	 * @param request the request
	 */
	private void sendCodeLog(String phone, Long landId, String landSubId, HttpServletRequest request){
		String ip = RequestTool.getIpAddr(request);
		Long appId = RequestLocal.get().getAppId();
		Long cid = RequestLocal.get().getCid();
		JSONObject json = new JSONObject();
		json.put("htmlId", landId);
		json.put("landSubId", landSubId);
		json.put("consumer_id", cid);
		json.put("appId", appId);
		String ua = request.getHeader("User-Agent");
		if (StringUtils.isNotBlank(ua) && ua.length() > 500) {
            ua = ua.substring(0, 499);
        }
		json.put("ua", ua);
		json.put("ip", ip);
		json.put("phone", phone);
		InnerLogService.landPageLog(LAND_GROUP, LAND_TYPE, json);
	}
	
    private void innerUserLog(LandUserInfo user) {
        try {
            JSONObject json = new JSONObject();
            json.put("land_id", user.getLandId());
            json.put("channel", user.getChannel());
            json.put("consumer_id", RequestLocal.get().getCid());
            json.put("app_id", RequestLocal.get().getAppId());
            json.put("user_name", user.getUserName());
            json.put("user_phone", user.getUserPhone());
            json.put("identification", user.getIdentification());
            json.put("sex", user.getSex());
            json.put("address", user.getAddress());
            json.put("birthday", user.getBirthday());
            json.put("region", user.getRegion());
            json.put("city", user.getCity());
            json.put("province", user.getProvince());
            json.put("info", user.getInfo());

            InnerLogService.landPageLog(1, 30, json);
        } catch (Exception e) {
            log.warn("user log error:" + e.getMessage());
        }
    }

    private String getInterfaceCode(HttpServletRequest request) {
        String code = request.getParameter("interfaceCode");
        if (StringUtils.isBlank(code)) {
            code = request.getParameter("code");
        }
        if (StringUtils.isBlank(code)) {
            throw new ActivityRuntimeException("code is null");
        }
        return code;
    }

	@RequestMapping("/drawcmapTrigger")
	public Result<AlipayCmapRsp> drawcmapTrigger(Long landId, @Pattern(regexp = "(^((17[0-9])|(14[0-9])|(13[0-9])|(15[^4,\\\\D])|(18[0,5-9]))\\\\d{8}$)", message = "请输入正确手机号") String phone, String oid, HttpServletRequest request) {
		LandUserInfoDto landUserInfo = new LandUserInfoDto();
		landUserInfo.setLandId(landId);
		landUserInfo.setUserPhone(phone);
		landUserInfo.setOrderId(oid);
		String typeStr = request.getParameter("type");
		String type;
		if ("duiba".equals(typeStr)) {
			type = "duiba";
		} else {
			type = "tuia";
		}
		landUserInfo.setAppName(type);
		return successResult(landService.drawcmapTrigger(landUserInfo, type));
	}


}
