package com.chinacreator.video.aspect;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import com.chinacreator.video.bean.OrderInfo;
import com.chinacreator.video.validate.BusiValidate;
import org.apache.commons.lang.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.BeanFactoryUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerExecutionChain;
import org.springframework.web.servlet.HandlerMapping;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.chinacreator.video.dto.DataOutPipe;
import com.chinacreator.video.exception.BussinessException;
import com.chinacreator.video.log.HandleLog;
import com.chinacreator.video.util.IpAddrUtil;
import com.chinacreator.video.util.RedisService;
import com.chinacreator.video.util.SpringUtils;

@Aspect
@Component
public class LogAspect {
	
    @Autowired
    RedisService redisService;

	@Autowired
	private BusiValidate busiValidate;

	private static Logger logger=LoggerFactory.getLogger("INFO");  
	
	
	@Pointcut("@annotation(com.chinacreator.video.annotation.Log)")
    public void webLog(){}

	@Around("webLog()")
	public Object showLog(ProceedingJoinPoint point) throws Throwable {
		long startTime = System.currentTimeMillis();
		HandleLog handleLog = new HandleLog();
		Object[] args = point.getArgs(); //获取当前执行方法中的执行参数
		ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
		HttpServletRequest request = attributes.getRequest();
		Signature signature = point.getSignature();
		String name = signature.getName(); //获取当前执行类中的执行方法
		String typeName = signature.getDeclaringTypeName(); //获取当前执行类
		handleLog.setTypeName(typeName);
		handleLog.setHostip(request.getServerName());
		handleLog.setHostport(String.valueOf(request.getServerPort()));
		handleLog.setAction(name);
		handleLog.setIp(IpAddrUtil.getIpAddr(request));
		if("huaweiCheckCapSmsCode".equals(name)){
			handleLog.setReq(JSON.toJSONString(args[0]));
		}else {
			handleLog.setReq(JSON.toJSONString(args));
		}
		Object result = null;
		try {
			result = point.proceed();
			handleLog.setResultcode("0");
			handleLog.setErrorinfo("");
			handleLog.setRsp(JSON.toJSONString(result));
		} catch (Exception e) {
			DataOutPipe<?> r = new DataOutPipe<>();
			if(e instanceof BussinessException) {
				 r.setErrorinfo(e.getMessage());
			     r.setResultcode(((BussinessException) e).getCode());
			}else {
				r.setErrorinfo("系统忙，请稍后再试,"+e.getMessage());
		        r.setResultcode("8000");
			}
			handleLog.setResultcode(r.getResultcode());
			handleLog.setErrorinfo(r.getErrorinfo());
			handleLog.setRsp(JSON.toJSONString(r));
			throw e;
		}finally {
			handleLog.setTimes((System.currentTimeMillis()-startTime)+"");
			logger.info(JSON.toJSONString(handleLog));
			//调用接口计数
			invokecount(handleLog);
		}
		return result;
	}
	
	/**
	 * handle接口调用计数
	 * @param handleLog
	 */
	private void invokecount(HandleLog handleLog){
		//com.chinacreator.video.web.HanddleControl
		//if(handleLog.getTypeName() != null && 
				//(handleLog.getTypeName().indexOf("HanddleControl") != -1 || handleLog.getTypeName().indexOf("CallSendcoController") != -1)
				//){
	    String action = handleLog.getAction();
	    //只统计handle统一订购接口及CAP短信订购接口checkCapSmsCode的数据
		if("handle".equals(action) || "checkCapSmsCode".equals(action) || "huaweiCheckCapSmsCode".equals(action)){
			//要忽略的异常编码
			//String ignoreResultcode = "10001,10002,10011,10012,10013,10023,10024,10005,10014,10015,10006,10007,10008,10009,80016,10040,10041,10042,10043";
			//List<String> ignoreList = Arrays.asList(ignoreResultcode.split(","));
			String currmonth = new SimpleDateFormat("yyyyMM").format(new Date());
			String currday = new SimpleDateFormat("yyyyMMdd").format(new Date());
			//按月计数
			pushInvokeCount(action, currmonth, handleLog);
			//按日计数
			pushInvokeCount(action, currday, handleLog);

		}
	}
	
	/**
	 * 保存到redis计数
	 * @param action
	 * @param currtimeflag
	 * @param handleLog
	 */
	private void pushInvokeCount(String action, String currtimeflag, HandleLog handleLog){
		try {
			String req = handleLog.getReq();
			String rsp = handleLog.getRsp();
			JSONObject reqjson = JSON.parseArray(req).getJSONObject(0);
			JSONObject rspjson = JSON.parseObject(rsp);
			String type = reqjson.getString("type"); //0订购，1退订
			String cpid = reqjson.getString("cpid"); 
			String spid = reqjson.getString("spid"); 
			String channel = reqjson.getString("channel"); 
			String subchannel = reqjson.getString("subchannel"); 
			String resultcode = rspjson.getString("resultcode"); //0成功，其他 失败
			if ("huaweiCheckCapSmsCode".equals(action)){
				OrderInfo orderInfo = new OrderInfo();
				type = "0";
				spid = reqjson.getString("productCode");
				orderInfo.setSpid(spid);
				channel = "200000000037";
				orderInfo.setCpid("0");
				busiValidate.valiCpSp(orderInfo);
				cpid = orderInfo.getCpid();
			}
			String unifychannel = ""; //主渠道加子渠道合并标识
			//子渠道不为空，要把两个渠道合并在一起为渠道标识
			if(!StringUtils.isEmpty(subchannel)){
				unifychannel = channel + subchannel;
			}
			//如果包含，或者cpid，spid为空，不处理
			//if(ignoreList.contains(resultcode) || StringUtils.isEmpty(cpid) || StringUtils.isEmpty(spid)) return;
			if(StringUtils.isEmpty(channel)) return; //渠道为空，可能是探测，不记录
						
			String mainkey = "univideo_invokecount_"+action+"_"+currtimeflag;
			String typetxt = "order";
			if(!"0".equals(type)){
				typetxt = "cancel";
			}
			/**
			   总访问量：
			 yyyymmdd_totalcount
			 */
			String itemkey = "totalcount";
			redisService.hincr(mainkey, itemkey, 1);
			
			String busires = "succ"; //办理结果
			if(!"0".equals(resultcode)){//失败
				busires = "fail"; //办理结果
				/**
				   办理失败编码统计：
				 channel_order_resultcode_fail_totalcount
				 channel_cancel_resultcode_fail_totalcount					 
				 */
				itemkey = channel+"_"+typetxt+"_"+resultcode+"_"+busires+"_"+"totalcount";
				redisService.hincr(mainkey, itemkey, 1);
				if(!StringUtils.isEmpty(unifychannel)){
					/**
					   办理失败编码统计：
					 channel+subchannel_order_resultcode_fail_totalcount
					 channel+subchannel_cancel_resultcode_fail_totalcount					 
					 */
					itemkey = unifychannel+"_"+typetxt+"_"+resultcode+"_"+busires+"_"+"totalcount";
					redisService.hincr(mainkey, itemkey, 1);
				}
			}
			/**
			总订购/退订量：
			order_totalcount，
			cancel_totalcount
			**/
			itemkey = typetxt+"_"+"totalcount";
			redisService.hincr(mainkey, itemkey, 1);
			/**
			 总订购退订成功/订购退订失败量：
			order_succ_totalcount，
			cancel_succ_totalcount，
			order_fail_totalcount，
			cancel_fail_totalcount
			**/
			itemkey = typetxt+"_"+busires+"_"+"totalcount";
			redisService.hincr(mainkey, itemkey, 1);
			/**
			SPID总订购/退订量：
			order_SPID_totalcount
			cancel_SPID_totalcount				  
			**/
			itemkey = typetxt+"_"+spid+"_"+"totalcount";
			redisService.hincr(mainkey, itemkey, 1);
			/**
			SPID总订购退订成功量/失败量：
			order_succ_CPID_SPID_totalcount
			order_fail_CPID_SPID_totalcount
			cancel_succ_CPID_SPID_totalcount
			cancel_fail_CPID_SPID_totalcount
			**/
			itemkey = typetxt+"_"+busires+"_"+cpid+"_"+spid+"_"+"totalcount";
			redisService.hincr(mainkey, itemkey, 1);
			/**
			 渠道总访问量：
			channel_totalcount  
			**/
			itemkey = channel+"_totalcount";
			redisService.hincr(mainkey, itemkey, 1);
			if(!StringUtils.isEmpty(unifychannel)){
				/**
				 渠道总访问量：
				channel+subchannel_totalcount  
				**/
				itemkey = unifychannel+"_totalcount";
				redisService.hincr(mainkey, itemkey, 1);
			}
			/**
			渠道总订购/退订量：
			channel_order_totalcount,
			channel_cancel_totalcount
			**/
			itemkey = channel+"_"+typetxt+"_"+"totalcount";
			redisService.hincr(mainkey, itemkey, 1);
			if(!StringUtils.isEmpty(unifychannel)){
				/**
				渠道总订购/退订量：
				channel+subchannel_order_totalcount,
				channel+subchannel_cancel_totalcount
				**/
				itemkey = unifychannel+"_"+typetxt+"_"+"totalcount";
				redisService.hincr(mainkey, itemkey, 1);
			}
			/**
			渠道总订购退订成功/订购退订失败量：
			channel_order_succ_totalcount, 
			channel_cancel_succ_totalcount, 
			channel_order_fail_totalcount, 
			channel_cancel_fail_totalcount
			**/
			itemkey = channel+"_"+typetxt+"_"+busires+"_"+"totalcount";
			redisService.hincr(mainkey, itemkey, 1);
			if(!StringUtils.isEmpty(unifychannel)){
				/**
				渠道总订购退订成功/订购退订失败量：
				channel+subchannel_order_succ_totalcount, 
				channel+subchannel_cancel_succ_totalcount, 
				channel+subchannel_order_fail_totalcount, 
				channel+subchannel_cancel_fail_totalcount
				**/
				itemkey = unifychannel+"_"+typetxt+"_"+busires+"_"+"totalcount";
				redisService.hincr(mainkey, itemkey, 1);
			}
			/**
			 渠道SPID总订购/退订量：
			channel_CPID_SPID_order_totalcount, 
			channel_CPID_SPID_cancel_totalcount
			**/
			itemkey = channel+"_"+cpid+"_"+spid+"_"+typetxt+"_"+"totalcount";
			redisService.hincr(mainkey, itemkey, 1);
			if(!StringUtils.isEmpty(unifychannel)){
				/**
				 渠道SPID总订购/退订量：
				channel+subchannel_CPID_SPID_order_totalcount, 
				channel+subchsnnel_CPID_SPID_cancel_totalcount
				**/
				itemkey = unifychannel+"_"+cpid+"_"+spid+"_"+typetxt+"_"+"totalcount";
				redisService.hincr(mainkey, itemkey, 1);
			}
			/**
			渠道SPID总订购退订成功/订购退订失败量：
			channel_CPID_SPID_order_succ_totalcount, 
			channel_CPID_SPID_cancel_succ_totalcount, 
			channel_CPID_SPID_order_fail_totalcount, 
			channel_CPID_SPID_cancel_fail_totalcount,
			**/
			itemkey = channel+"_"+cpid+"_"+spid+"_"+typetxt+"_"+busires+"_"+"totalcount";
			redisService.hincr(mainkey, itemkey, 1);	
			if(!StringUtils.isEmpty(unifychannel)){
				/**
				渠道SPID总订购退订成功/订购退订失败量：
				channel+subchannel_CPID_SPID_order_succ_totalcount, 
				channel+subchannel_CPID_SPID_cancel_succ_totalcount, 
				channel+subchannel_CPID_SPID_order_fail_totalcount, 
				channel+subchannel_CPID_SPID_cancel_fail_totalcount,
				**/
				itemkey = unifychannel+"_"+cpid+"_"+spid+"_"+typetxt+"_"+busires+"_"+"totalcount";
				redisService.hincr(mainkey, itemkey, 1);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}