package com.chinacreator.video.validate;

import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import com.chinacreator.video.bean.ChannelOrgMap;
import com.chinacreator.video.bean.OrderInfo;
import com.chinacreator.video.exception.BussinessException;
import com.chinacreator.video.mapper.CommConfDao;
import com.chinacreator.video.mapper.DictionaryDao;
import com.chinacreator.video.mapper.IpLimitConfigDao;
import com.chinacreator.video.util.IpAddrUtil;

@Component
public class IpValidate {
	
	public Logger logger = Logger.getLogger("testredis");
		
	@Autowired
	private CommConfDao commConfDao;
	
	@Autowired
	private DictionaryDao dictionaryDao;
	
	public void volidate(OrderInfo orderInfo) throws Exception{
		volidate(orderInfo, "0"); 
	}
	
	/**
	 * 二级配置渠道IP验证
	 * @param confip IP白名单
	 * @param orderInfo 用户信息
	 * @throws BussinessException
	 */
	public void volidate(String confip, OrderInfo orderInfo)throws BussinessException{
		ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
		HttpServletRequest request = attributes.getRequest();
		//取remoteaddr的IP的渠道配置，如果有配置，就只有配置的渠道才取
		String remoteAddrChannel = dictionaryDao.getValue("RemoteAddrChannel");
		//取请求所有IP地址
		List<String> ipList = IpAddrUtil.getIpAddrs(request, orderInfo, remoteAddrChannel); 
		//IP验证标识
		boolean ipvali = false;
		//IP不限制
		if("*".equals(confip)){
			ipvali = true;
		}else if(StringUtils.isNotEmpty(confip)){
			String [] ips = confip.split("\\|");
			for(String str : ips){
				//获得的IP里包含了白名单ip
				if(StringUtils.isNotEmpty(str) && ipList != null && ipList.contains(str)){
					ipvali = true;
				}
				//如果IP地址配置有*号，访问的IP包含*号前面的部分
				if(!ipvali && str.indexOf("*") != -1 && hasStartsWith(ipList, str)){
					ipvali = true;
				}
			}
		}
		
		if(!ipvali){
			//记录IP限制日志
			logger.info("IP被限制: ip=>"+ipList+"，channel=>"+orderInfo.getChannel()+"，调用接口=>"+(request.getHeader("x-forwarded-path"))+"，限制原因=>IP验证未通过");					
			throw new BussinessException("10005", "IP验证未通过:"+ipList);
		}
	}
	
	/**
	 * IP限制验证
	 * @param orderInfo
	 * @param busitype 业务类型，1查询，0办理	 
	 * @return
	 */
	public void volidate(OrderInfo orderInfo, String busitype) throws BussinessException{
		ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
		HttpServletRequest request = attributes.getRequest();
		//String ip = IpAddrUtil.getIpAddr2(request, orderInfo);
		//取remoteaddr的IP的渠道配置，如果有配置，就只有配置的渠道才取
		String remoteAddrChannel = dictionaryDao.getValue("RemoteAddrChannel");
		//取所有IP地址
		List<String> ipList = IpAddrUtil.getIpAddrs(request, orderInfo, remoteAddrChannel);
		//busitype 业务类型，1查询，0办理
		List<Map> list = null;
		try {

			//invokeface不为空
			if(StringUtils.isNotEmpty(orderInfo.getInvokeface()) && !"null".equals(orderInfo.getInvokeface())) {
				list = commConfDao.getIpLimitConfByInvokeface(busitype,orderInfo.getChannel(), orderInfo.getInvokeface());
			}else{
				list = commConfDao.getIpLimitConf(busitype,orderInfo.getChannel());
			}

			if(list == null || list.size() == 0){
				throw new BussinessException("10011", "IP限制无业务配置信息");
			}else{
				boolean result = false;
				boolean hasExists = false;
				boolean hasinvokeface = true; //是否有允许调指定接口
				//[{CHANNEL=TX20_wtqd, SPID=1167, IP=172.16.33.16, CPID=youtu}]
				for(Map map : list){
					//CPID级别验证
					if("*".equals(map.get("CPID"))){ //不限CPID
						hasExists = true;
					}else if(orderInfo.getCpid() != null && orderInfo.getCpid().equals(map.get("CPID")) 
							&& (orderInfo.getSpid() != null && orderInfo.getSpid().equals(map.get("SPID")) || "*".equals(map.get("SPID")))){
						hasExists = true;
					}
					
					if(hasExists){
						if("*".equals(map.get("IP"))){
							result = true;
						}else if(map.get("IP") != null && !"".equals(map.get("IP"))){
							String [] ips = map.get("IP").toString().split("\\|");
							for(String str : ips){
								//if(str != null && ip != null && str.contains(ip)){
								//获得的IP里包含了白名单ip
								if(str != null && ipList != null && ipList.contains(str)){
									result = true;
								}
								//如果IP地址配置有*号，访问的IP包含*号前面的部分
								//if(!result && str.indexOf("*") != -1 && ip.startsWith(str.split("[*]")[0])){
								if(!result && str.indexOf("*") != -1 && hasStartsWith(ipList, str)){
									result = true;
								}
							}
						}
						
						//有接口调用限制
						if(result && map.get("INVOKEFACE") != null && !"".equals(map.get("INVOKEFACE"))
								&& !map.get("INVOKEFACE").equals(orderInfo.getInvokeface())){
								hasinvokeface = false;							
						}
						
						break;
					}
				}
				if(!hasExists){ //无业务配置
					throw new BussinessException("10011", "IP限制无业务配置信息");
				}
				if(!result){
					throw new BussinessException("10005", "IP验证失败:"+ipList);
				}
				if(!hasinvokeface){
					throw new BussinessException("10011", "渠道【"+orderInfo.getChannel()+"】无【"+orderInfo.getInvokeface()+"】接口调用权限");
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
			if(e instanceof BussinessException) {
				//记录IP限制日志
				logger.info("IP被限制: ip=>"+ipList+"，dblist=>"+list+"，channel=>"+orderInfo.getChannel()+"，调用接口=>"+(request.getHeader("x-forwarded-path"))+"，限制原因=>"+((BussinessException)e).getCode()+"，"+((BussinessException)e).getMessage());
				throw e;
			}else {
				if(e.getMessage() != null && e.getMessage().indexOf("SQLException") != 0){
					throw new BussinessException("10014", "IP限制验证出现SQLException异常。");
				}else{
					throw new BussinessException("10015", "IP限制验证出现异常，"+e.getMessage());
				}
			}
		}
	}
	
	/**
	 * 判断是否模糊匹配
	 * @param ipList
	 * @param confip
	 * @return
	 */
	private boolean hasStartsWith(List<String> ipList, String confip){
		boolean res = false;
		for(String ip : ipList){
			if(ip.startsWith(confip.split("[*]")[0])){
				res = true;
				break;
			}
		}
		return res;
	}
}
