package com.chinacreator.process.job;

import com.chinacreator.common.exception.BusinessException;
import com.chinacreator.common.util.DESUtil;
import com.chinacreator.common.util.MD5;
import com.chinacreator.process.dao.BackBusiVipAsynDao;
import com.chinacreator.process.dao.DictionaryDao;
import com.chinacreator.process.util.HttpInvoke;
import com.chinacreator.process.util.JsonUtil;
import com.chinacreator.process.util.URLUtil;
import org.apache.log4j.Logger;
import org.quartz.DisallowConcurrentExecution;
import org.quartz.PersistJobDataAfterExecution;
import org.springframework.beans.factory.annotation.Autowired;

import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.*;


/**
 * 后向送会员异步处理
 * @author xu.zhou
 * @date 20200818
 */
@PersistJobDataAfterExecution
@DisallowConcurrentExecution
public class BackBusiVipAsynJob {

	private static Logger logger = Logger.getLogger("backbusivipsyn");
	
	@Autowired
	private BackBusiVipAsynDao asyndao;
	
	@Autowired
	private DictionaryDao dictionaryDao;
	
	public void doProcess() throws Exception {
		String trycount = dictionaryDao.getValue("vipasyntrycount");//后向产品赠送会员异步处理重试次数
		if(trycount == null || "".equals(trycount)) trycount = "3";
		logger.info(Thread.currentThread().getName()+"定时任务开始");
		long beginTime = System.currentTimeMillis();
		List<HashMap> list = asyndao.getVipAsynData(trycount);
		if(list != null && list.size() > 0){
			//推送月份
			String pushmonth = new SimpleDateFormat("yyyyMM").format(new Date());
			CountDownLatch threadSignal = new CountDownLatch(list.size());
			ExecutorService executorService = new ThreadPoolExecutor(12, 16, 10L, TimeUnit.MINUTES, new LinkedBlockingQueue<Runnable>(), new ThreadPoolExecutor.CallerRunsPolicy());
			List<HashMap> dataList = paraseData(list);
			logger.info("数据库有效订购的用户数："+dataList.size());
			
			for(HashMap vipmap : dataList){
				 BackBusiVipSynService continueService = new BackBusiVipSynService(list.size(),threadSignal,vipmap,asyndao,dictionaryDao);
		        	executorService.execute(continueService);
			}
			 executorService.shutdown();
		     try {
		          executorService.awaitTermination(5L, TimeUnit.MINUTES);
		     } catch (InterruptedException e) {
		          e.printStackTrace();
		     }
		}
		logger.info(Thread.currentThread().getName()+"定时任务完成，耗时："+(System.currentTimeMillis()-beginTime)/1000+" 秒");
	}
	
	/**
	 * 去除重复数据，防止赠送会员接口被并发限制
	 * @param dataList
	 * @return
	 */
	private List<HashMap> paraseData(List<HashMap> dataList){
		//去重复后的数据集
		List<HashMap> reDataList = new ArrayList<HashMap>(); 
		HashMap<String, List> tmpMap = new HashMap<String, List>();
		for (HashMap dataMap : dataList) {
			if(tmpMap.containsKey(dataMap.get("USERID").toString()+dataMap.get("CPID")+dataMap.get("SPID"))){
				logger.info("重复数据，"+dataMap.get("USERID")+dataMap.get("CPID")+dataMap.get("SPID"));
			}else{
				reDataList.add(dataMap);
				List tmpList = new ArrayList();
				tmpList.add(dataMap.get("SPID"));
				tmpMap.put(dataMap.get("USERID").toString()+dataMap.get("CPID")+dataMap.get("SPID"), tmpList);
			}
		}
		return reDataList;
	}
}

class BackBusiVipSynService implements Runnable {

	private static Logger log = Logger.getLogger("backbusivipsyn");
	private int totalSize;
	private CountDownLatch threadSignal;
	private HashMap vipmap;
	private DictionaryDao dictionaryDao;
	private BackBusiVipAsynDao asyndao;
	
	public BackBusiVipSynService(int totalSize,CountDownLatch threadSignal,HashMap vipmap,BackBusiVipAsynDao asyndao,DictionaryDao dictionaryDao){
		this.totalSize = totalSize;
		this.threadSignal = threadSignal;
		this.vipmap = vipmap;
		this.asyndao = asyndao;
		this.dictionaryDao = dictionaryDao;
	}
	
	@Override
	public void run() {
		long startime = System.currentTimeMillis();
		Map logMap = new HashMap();
		String id = vipmap.get("ID").toString();
		logMap.put("vipmap", vipmap);
		String resultcode = "-1";
		String errorinfo = "";
		String vipsendcode = "3"; //赠送会员结果标识，默认为失败
		try {
			//更新为正在赠送状态
			asyndao.updVipSendStatus(id);
			HashMap<String, String> remap = sendVip();
			if("0".equals(remap.get("vipsendcode"))){
				resultcode = "0";
				vipsendcode = "0";
				errorinfo = "赠送成功";
			}else{
				resultcode = remap.get("vipsendcode");
				errorinfo = remap.get("vipsendinfo");
			}
		} catch (Exception e) {
			if (e instanceof BusinessException) {
				errorinfo = ((BusinessException) e).getMessage();
				resultcode = ((BusinessException) e).getCode();
			}else{
				e.printStackTrace();
				resultcode = "8000";
				errorinfo = "处理数据出现异常，"+e.getMessage();
			}
		}finally {
			threadSignal.countDown();
			String time = System.currentTimeMillis()-startime+"";
			try{
				//更新赠送会员结果出现异常
				asyndao.updVipSendStatus(id, vipsendcode, time);
			}catch(Exception e){
				log.error(vipmap.get("USERID")+"更新赠送会员结果出现异常，"+e.getMessage());
			}
			//回调
			callBack(resultcode, errorinfo);
			//发送成功短信
			inserSmstMq(resultcode);
			//写日志
			logMap.put("resultcode", resultcode);
			logMap.put("errorinfo", errorinfo);
			logMap.put("time", time);
			logMap.put("count", totalSize+"/"+(totalSize - threadSignal.getCount()));
			log.info(JsonUtil.objectToJson(logMap));
		}
	}
	
	/**
	 * 推送办理成功的短信到队列
	 * @param orderInfo
	 */
	private void inserSmstMq(String resultcode){
		try{
			//赠送成功才发短信
			if(!"0".equals(resultcode)) return;
			
			String userid = vipmap.get("USERID").toString();
			if(userid == null || userid.length() != 11) return;
			String channel = vipmap.get("CHANNEL").toString();
			String cpid = vipmap.get("CPID").toString();
			String spid = vipmap.get("SPID").toString();
			Map<String, String> map = new HashMap<String, String>();
			map.put("userid", userid);
			map.put("cpid", cpid);
			map.put("spid", spid);
			map.put("result", "0");
			map.put("channel", "");
			map.put("style","0000");
			map.put("times", "");
			map.put("orderType", "");
			map.put("type", "cssms");
			map.put("busiType", "tran_succ");	//订购成功短信
			if("TX20_twback_qc".equals(channel)){//女王卡领取会员发短信，同样的SPID短信内容不同
				map.put("busiType", "qc_tran_succ");
			}
			String  mqReciveUrl = dictionaryDao.getValue("mqReciveUrl");
			URLUtil.post(mqReciveUrl, JsonUtil.objectToJson(map));
			
			//部分业务要发三条短信
			if(!"TX20_twback_qc".equals(channel)){
				map.put("busiType", "tran_succ2");	//订购成功短信
			}
			URLUtil.post(mqReciveUrl, JsonUtil.objectToJson(map));
			
			if(!"TX20_twback_qc".equals(channel)){
				map.put("busiType", "tran_succ3");	//订购成功短信
			}
			URLUtil.post(mqReciveUrl, JsonUtil.objectToJson(map));
		}catch (Exception e){
			e.printStackTrace();
			log.info(vipmap.get("ID")+"，发送成功短信失败");
		}
	}
    
	/**
	 * 调接口送会员
	 * @param orderInfo
	 * @return
	 * @throws Exception 
	 */
	private HashMap<String, String> sendVip() throws Exception{
		HashMap<String, String> remap = new HashMap<String, String>();
		String vipsendcode = "3"; //默认失败
		String vipsendinfo = "赠送失败";
		try {
			//http://114.255.201.228:86/activity/youkuHX
			String vipurl = this.dictionaryDao.getValue("backBusiVipUrl");
			String timestamp = (System.currentTimeMillis() / 1000) + "";
			String userid = vipmap.get("USERID").toString();
			String orderid = vipmap.get("ORDERID").toString();
			String channel = vipmap.get("CHANNEL").toString();
			String cpid = vipmap.get("CPID").toString();
			String spid = vipmap.get("SPID").toString();
			String pwd = "";
			List<HashMap> confList = asyndao.getBackBusiConf(cpid, spid);
			pwd = confList.get(0).get("PWD").toString();
			if("0".equals(confList.get(0).get("HASFH"))){ //是复合产品
				vipurl = this.dictionaryDao.getValue("backBusiGroupVipUrl");
			}
			userid = DESUtil.encode(userid, pwd);
			//MD5(orderid+userid+goodscode+pwd+timestamp)转换为十六进制ASCII 码字符串，共32 个字符，全小写 userid= Des(手机号码，pwd)
			//MD5(orderid+userid+timestamp+pwd)转换为十六进制ASCII 码字符串，共32 个字符，全小写
			String signature = MD5.MD5Encode(orderid + userid + timestamp + pwd);
			signature = signature.toLowerCase();
			vipurl = vipurl + "?userid=" + URLEncoder.encode(userid, "utf-8")+ "&orderid="+ orderid + "&cpid=" + cpid + "&spid=" + spid + "&timestamp="
					+ timestamp + "&signature=" + signature+ "&apptype=2";
			log.info("vipurl: "+vipurl);
			//http://114.255.201.228:86/activity/eshop/vip?userid=iafPbU9aRLghY%2FEVMXFeag%3D%3D&orderid=201906231206498662914&goodscode=pointshop130&timestamp=1561445765&signature=47fe0e3900b29ef88fd0889b7c0e4cc6&apptype=5
			String result = URLUtil.get(vipurl,30*1000); //调赠送会员接口，超时时间设置为10秒
			log.info("赠送会员重试结果=> userid: " +userid+", orderid: "+orderid+" , result: "+result);
			Map<?,?> map = JsonUtil.jsonToMap(result);
			//resultcode = (String)map.get("resultcode");
//			if("0".equals(map.get("resultcode"))){
//				vipsendcode = "0";
//			}
			vipsendcode = map.get("resultcode")+"";
			vipsendinfo = map.get("errorinfo")+"";
		} catch (Exception e) {
			e.printStackTrace();
			log.error("userid: "+vipmap.get("USERID")+"赠送会员失败，"+e);
			if(e.getMessage() != null && e.getMessage().indexOf("TimeoutException") != -1){//超时异常
				throw new BusinessException("9070","赠送会员超时", new String[0]);
			}else{
				throw new BusinessException("9002","赠送会员未成功", new String[0]);
			}
		}
		
		remap.put("vipsendcode", vipsendcode);
		remap.put("vipsendinfo", vipsendinfo);
		
		return remap;
	}
	
    /**
     *  回调通知
     * @param orderBean
     * @return 0成功，1未回调，2出现异常
     */
    private String callBack(String resultcode, String resultinfo){
    	String res = "1"; 
    	try {
    		String trycountconf = dictionaryDao.getValue("vipasyntrycount");
    		String trycount = vipmap.get("RETRYCOUNT").toString();
    		String userid = vipmap.get("USERID").toString();
			String orderid = vipmap.get("ORDERID").toString();
			String channel = vipmap.get("CHANNEL").toString();  
			String id = vipmap.get("ID").toString(); 
    		//判断重试是否已是最大次数
    		if(!"0".equals(resultcode) && Integer.parseInt(trycount)+1 < Integer.parseInt(trycountconf)){
    			return null;
    		}
    		//当会员赠送失败时，反查一下会员赠送日志表，看是否真的赠送失败，防止调接口超时获取不到真实赠送结果
    		if(!"0".equals(resultcode)){
    			if(asyndao.getVipSendRes(orderid)){
    				resultcode = "0";
    				resultinfo = "OK";
    			}
    		}

    		HashMap channelInfo = asyndao.getChannelPwdByChannel(channel);

    		String pwd = channelInfo.get("PASSWORD")+"";
    		userid = DESUtil.encode(userid, pwd);
    		userid =  URLEncoder.encode(userid, "utf-8");
			String vipRetryCallBackUrl = this.dictionaryDao.getValue("vipRetryCallBackUrl");//回调接口地址
			vipRetryCallBackUrl += "?orderid="+orderid+"&resultcode="+resultcode+"&resultinfo="+URLEncoder.encode(resultinfo,"utf-8")+"&userid="+userid;	
			log.info("===========回调地址："+vipRetryCallBackUrl);
			String result = HttpInvoke.sendhttpsReq("GET", vipRetryCallBackUrl, "", null, 60*1000, "TLSv1.2");
			//String result = URLUtil.get(vipRetryCallBackUrl,60*1000); //调赠送会员接口，超时时间设置为10秒
			log.info("回调通知接口返回信息=>userid: " +userid+", orderid: "+orderid+", result: "+result);
			Map<?,?> map = JsonUtil.jsonToMap(result);
			res = (String)map.get("result");
		} catch (Exception e) {
			res = "2";
			e.printStackTrace();
			log.error("id=>"+vipmap.get("ID")+"，回调接口出现异常，"+e.getMessage());
		} 
    	return res;
    }
}
