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

import java.io.IOException;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javax.servlet.http.HttpServletResponse;

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.stereotype.Service;

import cn.com.duiba.tuia.activity.center.api.dto.LandInterfaceLogDto;
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.tuia.activity.center.api.remoteservice.RemoteLandService;
import cn.com.duiba.wolf.utils.BeanUtils;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.duiba.tuia.youtui.web.biz.land.LandInfoOpt;
import com.duiba.tuia.youtui.web.biz.land.param.InsuranceResponseFactory;
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.biz.land.param.RequestParamFactory;
import com.duiba.tuia.youtui.web.constant.Constants;
import com.duiba.tuia.youtui.web.constant.ErrorCode;
import com.duiba.tuia.youtui.web.constant.LandChannel;
import com.duiba.tuia.youtui.web.exception.ActivityException;
import com.duiba.tuia.youtui.web.model.req.CustomUserFormInfo;
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.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.SmsService;
import com.duiba.tuia.youtui.web.tool.HttpRequestTool;
import com.duiba.tuia.youtui.web.tool.RequestLocal;
import com.google.common.collect.Lists;

@Service
public class LandServiceImpl implements LandService{
	private static final Logger log = LoggerFactory.getLogger(LandServiceImpl.class);

	private static final Map<Integer,Map<String,Integer>> NEWTANK_FEE;//新旦保费表
	static {
        NEWTANK_FEE = new HashMap<>();

        Map<String, Integer> age8 = new HashMap<>();//0-8岁保费表
        age8.put("28000",1608);
        age8.put("38000",1848);
        age8.put("48000",2100);
        age8.put("50000",2136);
        age8.put("80000",2868);

        Map<String, Integer> age17 = new HashMap<>();//9-17岁保费表
        age17.put("28000",1680);
        age17.put("38000",1944);
        age17.put("48000",2220);
        age17.put("50000",2256);
        age17.put("80000",3060);
        age17.put("100000",3600);
        age17.put("150000",4932);
        age17.put("200000",6576);

        Map<String, Integer> age50 = new HashMap<>();//18-50岁保费表
        age50.put("50000",2412);
        age50.put("80000",3288);
        age50.put("100000",3864);
        age50.put("150000",5316);
        age50.put("200000",7068);
        age50.put("250000",8532);
        age50.put("300000",9984);
        age50.put("350000",11424);
        age50.put("400000",12876);
        age50.put("500000",15780);
        age50.put("600000",19320);
        age50.put("700000",22212);
        age50.put("800000",25128);
        age50.put("1000000",30912);

        Map<String, Integer> age55 = new HashMap<>();//51-55岁保费表
        age55.put("50000",2808);
        age55.put("80000",3804);
        age55.put("100000",4476);
        age55.put("150000",6144);
        age55.put("200000",8172);
        age55.put("250000",9852);
        age55.put("300000",11520);
        age55.put("350000",13188);
        age55.put("400000",14856);
        age55.put("500000",18204);
        age55.put("600000",22284);
        age55.put("700000",25632);
        age55.put("800000",28968);
        age55.put("1000000",35652);

        NEWTANK_FEE.put(8, age8);
        NEWTANK_FEE.put(17, age17);
        NEWTANK_FEE.put(50, age50);
        NEWTANK_FEE.put(55, age55);

    }
	
	@Autowired
	private LandInfoOpt landInfoOpt;
	@Autowired
	private RequestParamFactory requestParamFactory;
	@Autowired
	private InterfaceService interfaceService;
	@Autowired
	private InsuranceResponseFactory insuranceResponseFactory;
	@Autowired
	private RemoteLandService remoteLandService;
	@Autowired
	private SmsService smsService;
	@Autowired
	private CommonService commonService;

	@Override
	public void LandingPage(LandUserInfo info, LandExtendParam extendParam, HttpServletResponse response) throws ActivityException {
		String channel = info.getChannel();
		switch (channel) {
			case LandChannel.HEIKA_CHANNEL://只需要保存
			case LandChannel.SJD_CHANNEL:
			case LandChannel.LEKESI:
				landInfoOpt.save(info, extendParam);
				break;
			case LandChannel.OPPEIN:
			case LandChannel.AUPU:
			    if(!this.smsVerify(info.getUserPhone(), extendParam.getSmsCode(), channel)){
			        throw new ActivityException(ErrorCode.E0100004);
			    }
				if(isExist(info.getUserPhone(),info.getLandId())){
					throw new ActivityException(ErrorCode.E0100008);
				}
				landInfoOpt.save(info, extendParam);
				break;
			case LandChannel.SHA_JIN://越南沙金，短信验证码，生成订单号
				if(!this.smsVerify(info.getUserPhone(), extendParam.getSmsCode(), channel)){
					throw new ActivityException(ErrorCode.E0100004);
				}
				String orderId = this.commonService.getNextOrderId(null);
				info.setOrderId(orderId);
				landInfoOpt.save(info,extendParam);
				break;
			case LandChannel.HOME_EXPO:
				if (isExist(info.getUserPhone(), info.getLandId())) {
					throw new ActivityException(ErrorCode.E0100008);
				}
				landInfoOpt.save(info, extendParam);
				break;
			case "gggggg"://只需要转发
				LandParamI sendParam = requestParamFactory.getLandParam(info);
				HttpRequestTool.requestByPost(sendParam.getRequestUrl(info), sendParam.getRequestParam(info));
				break;
			case "hhhhhh"://保存和转发
				landInfoOpt.save(info, extendParam);
				LandParamI saveParam = requestParamFactory.getLandParam(info);
				HttpRequestTool.requestByPost(saveParam.getRequestUrl(info), saveParam.getRequestParam(info));
				break;
			case "jjjjjj"://保存和重定向（只支持get，不支持post）
				landInfoOpt.save(info, extendParam);
				LandParamI redirectParam = requestParamFactory.getLandParam(info);
				String url = getRedirectUrl(redirectParam.getRequestUrl(info), redirectParam.getRequestParam(info));
				try {
					response.sendRedirect(url);
				} catch (IOException e) {
					log.error("落地页转发失败信息 errormsg={}",e.getMessage());
				}
				break;
			default://不做任何操作
				break;
		}
		
	}

	@Override
	public Boolean isExist(String phone, Long landId) {
		return landInfoOpt.isExist(landId, phone);
	}
	
	@Override
	public LandParamI getParam(LandUserInfo info){
		return requestParamFactory.getLandParam(info);
	}
	
	private String getRedirectUrl(String url, Map<String, Object> param){
		StringBuilder sb = new StringBuilder(url);
		sb.append("?");
		for(Entry<String, Object> entry: param.entrySet()){
			sb.append(entry.getKey());
			sb.append("=");
			sb.append(entry.getValue());
			sb.append("&");
		}
		return sb.toString();
	}

    @Override
    public InsuranceResultRsp insurancePage(LandUserInfo info, LandExtendParam extendParam) {
        String channel = info.getChannel();
        InsuranceResultRsp rs;
        Map<String,Object> params = BeanUtils.transBeanToMap(info);
        params.put(Constants.VALUENAME.SUB_CHANNEL, extendParam.getSubchannel());
        switch (channel) {
            case LandChannel.NEWTANK:
                params.put("effectiveTimes", parseEffectiveTimes());
				rs = getInsuranceResultRsp(info, extendParam, channel, params);
				break;
            case LandChannel.HEINIU:
				rs = getInsuranceResultRsp(info, extendParam, channel, params);
                break;
            default:
                rs = null;
        }
        return rs;
    }

	private InsuranceResultRsp getInsuranceResultRsp(LandUserInfo info, LandExtendParam extendParam, String channel, Map<String, Object> params) {
		InsuranceResultRsp rs;
		landInfoOpt.save(info, extendParam);//保存用户信息
		String resp2 = this.interfaceService.invoke(extendParam.getInterfaceCode(), params);//调用第三方接口
		rs = insuranceResponseFactory.getInsuranceResult(channel, resp2);//解析返回内容
		rs.setUserId(info.getUserId());
		saveInsuranceResult(info,rs,resp2,extendParam.getConsumerId());
		return rs;
	}


	/**
	 * 保存投保结果
	 * @param info
	 * @param rsp
	 * @param response
	 * @param consumerId
	 */
	private void saveInsuranceResult(LandUserInfo info,InsuranceResultRsp rsp,String response,Long consumerId) {
		LandInterfaceLogDto dto = new LandInterfaceLogDto();
		dto.setUserId(info.getUserId());
		dto.setChannel(info.getChannel());
		dto.setResponseBody(response);
		dto.setConsumerId(consumerId);
		dto.setLandId(info.getLandId());
		dto.setOrder(rsp.getInsuredOrder());
		dto.setMessage(rsp.getDesc());
		dto.setStatus(rsp.getStatus());
		dto.setUrl(rsp.getInsuredUrl());
		this.remoteLandService.insertLandInterfaceLog(dto);
	}

	/**
	 * parseEffectiveTimes:(设置生效时间). <br/>
	 * 新旦保险接口必填参数。
	 * @return
	 */
	private long parseEffectiveTimes() {
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DAY_OF_MONTH, 1);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime().getTime();
    }

    @Override
    public Boolean updateUserInfo(LandUserInfo info, String interfaceCode) {
        String channel = info.getChannel();
        switch (channel) {
            case LandChannel.NEWTANK:
                if (info.getUserId() == null) {
                    this.landInfoOpt.save(info, new LandExtendParam());
                } else {
                    info.setInfo(info.getQuestionnaire());//用户问券信息 保存到info字段中
                    this.landInfoOpt.update(info);
                }
				invokeNewtank(info);
				break;
            default:
                break;
        }
        return Boolean.TRUE;
    }

	@Override
	public AlipayCmapRsp drawcmapTrigger(LandUserInfoDto landUserInfoDto, String type) {
		landUserInfoDto.setChannel(LandChannel.ALIPAY);
		landUserInfoDto.setConsumerId(RequestLocal.get().getCid());
		landUserInfoDto.setAppId(RequestLocal.get().getAppId());
		return remoteLandService.drawcmapTriggerNew(landUserInfoDto, type);
	}

	/*
	 * 调用新旦用户信息更新接口
	 */
	private void invokeNewtank(LandUserInfo info) {
		if (StringUtils.isNotBlank(info.getUid())) {
			JSONObject req = new JSONObject();
			req.put("type", 2);
			req.put("questionnaire",JSONArray.parse(info.getQuestionnaire()));
			req.put("uId", info.getUid());
			req.put("channelCode", "duiba");
			req.put("tag", getNewtankTag(info));
			String request = req.toJSONString();
			String response = HttpRequestTool.requestByPost("http://www.newtank.cn/newtank/thp/extrainfo",req.toJSONString());


			LandInterfaceLogDto dto = new LandInterfaceLogDto();
			dto.setUserId(info.getUserId());
			dto.setChannel(info.getChannel());
			dto.setConsumerId(RequestLocal.get().getCid());
			dto.setLandId(info.getLandId());
			dto.setRequestBody(request);
			dto.setResponseBody(response);
			this.remoteLandService.insertLandInterfaceLog(dto);
		}
	}

	/*
	 * 新旦用户信息接口tag字段
	 */
	private JSONObject getNewtankTag(LandUserInfo info) {
		JSONObject tag = null;
		if (info.getAge() != null && StringUtils.isNotBlank(info.getFee())) {
			tag = new JSONObject();
			tag.put("insuranceName", "鸿运随行");//保险名称
            tag.put("annualPremium", getNewtankAnnualPremium(info.getAge(), info.getFee()));//年化保费
            tag.put("amount", info.getFee());//保额
			tag.put("paymentType", "MONTHLY");//缴费方式
		}
		return tag;
	}

	/*
	 * 获取新旦年化保费
	 * 由年龄与保额决定，其对应关系写死在 NEWTANK_FEE 中
	 *
	 */
    private Integer getNewtankAnnualPremium(int age,String amount) {
        int maxAge;
        if (age <= 8) {
            maxAge = 8;
        } else if (age <= 17) {
            maxAge = 17;
        } else if (age <= 50) {
            maxAge = 50;
        } else if (age <= 55) {
            maxAge = 55;
        } else {
            return null;
        }
        return NEWTANK_FEE.get(maxAge).get(amount);

    }

	private boolean smsVerify(String phone,String smsCode,String channel){
        if(StringUtils.isAnyBlank(phone,smsCode,channel)){
            return false;
        }
        return this.smsService.verify(phone, smsCode, channel);
    }

    @Override
    public void submitForm(LandUserFormInfo landUserFormInfo, LandExtendParam extendParam) throws ActivityException {
        // 默认渠道
        if (!LandChannel.FORMTEMPLATE.equals(landUserFormInfo.getChannel())) {
            throw new ActivityException(ErrorCode.E0100010);
        }
        // 验证码校验
        if (StringUtils.isNoneBlank(landUserFormInfo.getSmsCode()) && !this.smsVerify(landUserFormInfo.getUserPhone(), landUserFormInfo.getSmsCode(), landUserFormInfo.getChannel())) {
            throw new ActivityException(ErrorCode.E0100004);
        }
        // 自定义字段保存
        String customInfoStr = checkCustomUserFormInfo(landUserFormInfo.getListUserInfo());
        LandUserInfo landUserInfo = BeanUtils.copy(landUserFormInfo, LandUserInfo.class);
        landUserInfo.setInfo(customInfoStr);
        landUserInfo.setBirthday(getBirthday(landUserFormInfo.getBirthday()));
        landInfoOpt.save(landUserInfo, extendParam);
        return;
    }
    private Long getBirthday(String birthday) {
        try {
            String d1 = birthday.replaceAll(" ", "");
            String[] d2 = d1.split("年");
            String[] d3 = d2[1].split("月");
            String[] d4 = d3[1].split("日");
            
            Calendar cal1 = Calendar.getInstance();
            cal1.set(Integer.parseInt(d2[0]), Integer.parseInt(d3[0])-1, Integer.parseInt(d4[0]), 0, 0, 0);
            return cal1.getTimeInMillis();
        } catch (Exception e) {
            log.error("get birthday error, String info =[{}]", birthday);
            return null;
        }
    }

    /**
     * 
     * checkCustomUserFormInfo:(自定义表单校验). <br/>
     *
     * @author chencheng
     * @param ListUserInfo 自定义表单数据
     * @return
     * @throws ActivityException
     * @since JDK 1.8
     */
    private String checkCustomUserFormInfo(String listUserInfo) throws ActivityException {
        
        if (StringUtils.isEmpty(listUserInfo)) {
            return null;
        }
        List<CustomUserFormInfo> userInfoList = Lists.newArrayList();
        try {
            userInfoList = JSONArray.parseArray(StringEscapeUtils.unescapeHtml(listUserInfo), CustomUserFormInfo.class);
        } catch (Exception e) {
            log.error("get listUserInfo error, String info =[{}]", listUserInfo);
            return null;
        }
        
        JSONObject jsonObject = new JSONObject();
        for (CustomUserFormInfo userFormInfo : userInfoList) {
            if (StringUtils.isNotBlank(userFormInfo.getValue())) {
                jsonObject.put(userFormInfo.getName(), userFormInfo.getValue());
            }
        }
        return jsonObject.toJSONString();
    }
    
}
