package com.chinacreator.video.service;

import java.net.URLEncoder;
import java.util.List;
import java.util.Map;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.chinacreator.video.bean.ChannelBean;
import com.chinacreator.video.bean.CpSpBean;
import com.chinacreator.video.bean.OrderInfo;
import com.chinacreator.video.exception.BussinessException;
import com.chinacreator.video.mapper.ChannelDao;
import com.chinacreator.video.mapper.CpSpDao;
import com.chinacreator.video.mapper.DictionaryDao;
import com.chinacreator.video.mapper.PointShopDao;
import com.chinacreator.video.util.DesUtil;
import com.chinacreator.video.util.MD5;
import com.chinacreator.video.util.RedisService;
import com.chinacreator.video.validate.ChannelValidate;
import com.chinacreator.video.validate.IpValidate;
import com.chinacreator.video.validate.MobValidate;
import com.chinacreator.video.validate.TimetampValidate;

@Component
public class BackBusiOrderService {
	private static final  Logger logger = LoggerFactory.getLogger(BackBusiOrderService.class);
	
	private static final  Logger log = LoggerFactory.getLogger("commonOrder");
	
	@Autowired
	private CpSpDao CpSpDao;
	
	@Autowired
	private DictionaryDao dictionaryDao;
	
	@Autowired
	private ChannelDao channelDao;
	@Autowired
	private PointShopDao pointShopDao;
	@Autowired
	private ChannelValidate channelValidate;
	
	@Autowired
	private IpValidate ipValidate;
	
	@Autowired
	private MobValidate mobValidate;
	
	@Autowired
	private TimetampValidate timetampValidate;
	
	@Autowired
	RedisService redisService;
	
	@Autowired
	QueenCardService service;
	
	
	@Autowired
	CommonService commonService;
	
	public void busiCheck(OrderInfo orderInfo) throws Exception{
		
		valiParams(orderInfo);
		
		//timetamp验证
		timetampValidate.validate(orderInfo.getTimestamp());
		//渠道验证
		channelValidate.validate(orderInfo.getChannel());
		//ip验证
		ipValidate.volidate(orderInfo);
		//签名验证
		signValidate(orderInfo);
		//手机号码验证
		//mobValidate.validate(orderInfo);
		mobile(orderInfo);
		//女王卡订购验证
		qcOrderVali(orderInfo);		
		//省份办理限制验证
		commonService.valiChannelSpidLimit(orderInfo);
		
		if(!"TX20_twback_qc".equals(orderInfo.getChannel())){	
			//办理后向并发控制
			vistValiByBackBusi(orderInfo);
		}
	}
	
	private void mobile(OrderInfo orderInfo) throws Exception {
		String userid = orderInfo.getUserid();
		if(StringUtils.isEmpty(userid)) {
			throw new BussinessException("10007", "手机号不能为空");
		}
		CpSpBean cpSpBean = CpSpDao.getCpSp(orderInfo.getCpid(), orderInfo.getSpid());
		if(cpSpBean == null) {
			throw new BussinessException("10010", "cpid/spid错误");
		}
		ChannelBean channelBean = channelDao.queryChannel(orderInfo.getChannel());
		try {
			userid = DesUtil.decode(userid, channelBean.getPassword());
			if(isValid(userid,orderInfo.getChannel(),orderInfo.getSpid())){
				orderInfo.setUserid(userid);
			}else{
				throw new BussinessException("10009", "手机号错误");
			}	
		} catch (Exception e) {
			if(e instanceof BussinessException) {
				throw e;
			}else {
				throw new BussinessException("10008", "手机号加密错误");
			}
		}
	}
	
	/**
     * 支持QQ号与手机号
     * zzb 2020/02/18
	 * @throws BussinessException 
     */
	private boolean isValid(String usermob,String channel,String spid) throws BussinessException{
        if (usermob == null) {
            return false;
        }
        usermob = usermob.replaceAll("[\\s-]", "");
        if(!usermob.matches("^[0-9]*$")){
        	return false;
        }else{
        	if(usermob.length() < 11){//QQ号
        		if(StringUtils.equals("TX20_twback_old", channel)||StringUtils.equals("TX20_twback", channel)){
            		List<Map> goodsCodeList = pointShopDao.getPointShopConfigBySpid(spid);
                    if(goodsCodeList != null && goodsCodeList.size()>0){
                    	Map goodsCodeMap = goodsCodeList.get(0);
                		//判断是否配置netdays参数
                		if(!"1".equals(goodsCodeMap.get("BUSITYPE"))){
                			return false;
                		}
                    }
        		}else{
        			return false;
                }
            }
        }
        return true;
	}
	/**
	 * 签名验证
	 * @param orderInfo
	 * @throws Exception
	 */
	public void signValidate(OrderInfo orderInfo) throws Exception {
		String lcalsign = getSign(orderInfo);
		lcalsign += channelDao.queryChannel(orderInfo.getChannel()).getPassword();
		log.info("=========lcalsign:"+lcalsign);
		lcalsign = MD5.MD5Encode(lcalsign);
		log.info("=========Md5lcalsign:"+lcalsign);
		log.info("=========inlcalsign:"+orderInfo.getSignature());
		if(!lcalsign.equals(orderInfo.getSignature())) {
			throw new BussinessException("10006", "签名校验失败");
		}
	}
	
	/**
	 * 参数验证
	 * @param orderInfo
	 * @throws BussinessException
	 */
	private void valiParams(OrderInfo orderInfo) throws Exception{
		String cpid = orderInfo.getCpid();
		String spid = orderInfo.getSpid();
		String channel = orderInfo.getChannel();
		String userid = orderInfo.getUserid();
		String timestamp = orderInfo.getTimestamp();
		String orderid = orderInfo.getOrderid();
		String subchannel = orderInfo.getSubchannel();
		if(StringUtils.isEmpty(orderid) || StringUtils.isEmpty(cpid) || StringUtils.isEmpty(spid) 
				|| StringUtils.isEmpty(userid) || StringUtils.isEmpty(timestamp)
				|| StringUtils.isEmpty(channel)) {
			throw new BussinessException("80015", "参数不合法");
		}	
		if(subchannel != null && subchannel.length()>60){
			throw new BussinessException("80015", "参数不合法");
		}
	}
	
	/**
	 * 拼接签名信息 cpid+spid+userid+type+channel+timestamp
	 * @param orderInfo
	 * @return
	 */
	private String getSign(OrderInfo orderInfo) {
		if (orderInfo == null) {
			return "";
		}
		StringBuilder strb = new StringBuilder();
		strb.append(orderInfo.getOrderid());
		strb.append(orderInfo.getCpid());
		strb.append(orderInfo.getSpid());
		strb.append(orderInfo.getUserid());
		strb.append(orderInfo.getChannel());
		if(orderInfo.getSubchannel() != null){
			strb.append(orderInfo.getSubchannel());
		}
		strb.append(orderInfo.getTimestamp());
		return strb.toString();
	}
	
	/**
	 * 拼接转发URL参数
	 * @param orderInfo
	 * @return
	 * @throws BussinessException
	 */
	private String getParams(OrderInfo orderInfo) throws BussinessException{
		String params = "";
		try {
			String cpid = orderInfo.getCpid();
			String spid = orderInfo.getSpid();
			//String type = orderInfo.getType();
			String userid = orderInfo.getUserid();
			String timestamp = orderInfo.getTimestamp();
			String orderid = orderInfo.getOrderid();
			String pwd = CpSpDao.getCpSp(orderInfo.getCpid(), orderInfo.getSpid()).getPwd(); //TB_CP_ACCOUNT_CONFIG表NETPWD字段
			params += "orderid="+orderid+"&ordertype=0&apptype=2&channel="+orderInfo.getChannel()+"&cpid="+cpid+"&spid="+spid+"&timestamp="+timestamp+"&subchannel="+orderInfo.getSubchannel();
			userid = DesUtil.encode(userid, pwd); //手机号码加密
			//数据的签名： Md5(orderid+cpid+spid+userid+type+timestamp+pwd)
			String signature = MD5.MD5Encode(orderid + cpid + spid + userid + timestamp + pwd);
			params += "&userid="+URLEncoder.encode(userid, "utf-8")+"&signature="+signature; //重新编码
		} catch (Exception e) {
			e.printStackTrace();
			throw new BussinessException("80013", "组建调用参数出现异常，"+e.getMessage());
		}
	
		return params;
	}
	
	/**
	 * 获取订购url
	 * @param orderInfo
	 * @return
	 * @throws Exception
	 */
	public String getOrderUrl(OrderInfo orderInfo) throws Exception {
		String orderUrl = dictionaryDao.getValue("commonOrderUrl")+"backorder.do?";
		orderUrl += this.getParams(orderInfo);
		return orderUrl;
	}
	
	/**
	 * 女王卡订购验证
	 * @param orderInfo
	 * @throws Exception
	 */
	private void qcOrderVali(OrderInfo orderInfo) throws Exception {
		if("TX20_twback_qc".equals(orderInfo.getChannel())){	
			//验证访问限制
			vistVali(orderInfo);
			
			try {
				service.valiVipmon(orderInfo);
			} catch (Exception e) {
				e.printStackTrace();
				if(e instanceof BussinessException) {
					String errorinfo = ((BussinessException) e).getMessage();
					throw new BussinessException("8000", "女王卡业务办理验证失败："+errorinfo);
				}else {
					throw e;
				}
			}
		}
	}
	
	/**
	 * 判断订购月份是否大于或者等于当前月份
	 * @param ordertime
	 * @param type 0判断订购月份是否大于当前月份，1判断订购月份是否等于当前月份
	 * @return
	 */
	private boolean valiOrderDate(String ordertime, int type){
		boolean res = false;
		//当前年月
		String currDate = new SimpleDateFormat("yyyyMM").format(new Date());
		String tmpDate = ordertime.substring(0,6);
		if(type == 0){
			if(Long.parseLong(currDate) > Long.parseLong(tmpDate)){
				res = true;
			}
		}else{
			if(Long.parseLong(currDate) == Long.parseLong(tmpDate)){
				res = true;
			}
		}

		return res;
	}
	
	/**
	 * 验证访问限制，1分钟内同一业务只能办理一次
	 * @param orderInfo
	 * @throws Exception
	 */
	private void vistVali2(OrderInfo orderInfo) throws Exception {
		Object obj = redisService.get(orderInfo.getChannel()+"_"+orderInfo.getUserid());
		if(obj != null){
			throw new BussinessException("8000", "女王卡业务办理验证失败：指定时间内重复请求");	
		}else{
			redisService.set(orderInfo.getChannel()+"_"+orderInfo.getUserid(), new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()), Long.parseLong("60"));
		}
	}
	
	/**
	 * 验证访问限制，1分钟内同一业务只能办理一次
	 * @param orderInfo
	 * @throws Exception
	 */
	private void vistVali(OrderInfo orderInfo) throws Exception {
		String [] params = new String [2];
		params[0] = orderInfo.getChannel();
		params[1] = orderInfo.getUserid();
		if(commonService.vistVali(params, "qcOrder")){
			throw new BussinessException("8000", "女王卡业务办理验证失败：指定时间内重复请求");	
		}
	}
	
	/**
	 * 验证访问限制，1分钟内同一业务只能办理一次
	 * @param orderInfo
	 * @throws Exception
	 */
	private void vistValiByBackBusi(OrderInfo orderInfo) throws Exception {
		String [] params = new String [3];
		params[0] = orderInfo.getChannel();
		params[1] = orderInfo.getUserid();
		params[2] = orderInfo.getSpid();
		if(commonService.vistVali2(params, "backbusi")){
			throw new BussinessException("8000", "指定时间内重复请求");	
		}
	}
	
	/**
	 * 判断是否当月退订
	 * @param canceltime
	 * @return
	 * @throws Exception
	 */
	private boolean valiCancelDate(String canceltime)throws Exception {
		boolean res = false;
		//当前年月
		String currDate = new SimpleDateFormat("yyyyMM").format(new Date());
		String tmpDate = canceltime.substring(0,6);
		if(Long.parseLong(currDate) == Long.parseLong(tmpDate)){
			res = true;
		}
		return res;
	}
	
	/**
	 * 判断当前日号是否大于或等于5
	 * @return
	 */
	private boolean valiDay(){
		boolean res = false;
    	//当前时间
    	Calendar cal_curr = Calendar.getInstance();
    	if(cal_curr.get(Calendar.DATE) >= 5){
    		res = true;
    	}
    	return res;
	}
}
