package com.philisense.www.aspect;


import com.philisense.www.annotation.log.OperateLog;
import com.philisense.www.service.ProOperlogService;
import com.philisense.www.utils.ActiveUserUtils;
import com.philisense.www.utils.IpAdrressUtil;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.*;

@Component
@Aspect
public class LogAspect {

    @Autowired
    private ProOperlogService proOperlogService;
    /**
     * 配置切入点
     */
    @Pointcut("@annotation(com.philisense.www.annotation.log.OperateLog)")
    public void logPointcut() {
        // 该方法无方法体,主要为了让同类中其他方法使用此切入点
    }

    /**
     * 配置环绕通知,使用在方法logPointcut()上注册的切入点
     *
     * @param joinPoint join point for advice
     */
    @Around("logPointcut()")
    public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {

        Map<String, Object> params = new HashMap<String, Object>();

        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = ((ServletRequestAttributes)requestAttributes).getRequest();
        String url = request.getRequestURL().toString();
        String method = request.getMethod();
        String uri = request.getRequestURI();
        String queryString = request.getQueryString();
        Map<String, String> headermap = new HashMap<String, String>();
        Enumeration<String> headerNames = request.getHeaderNames();
        while (headerNames.hasMoreElements()) {
            String key = (String) headerNames.nextElement();
            // 排除Cookie字段
            if (key.equalsIgnoreCase("Cookie")) {
                continue;
            }
            String value = request.getHeader(key);
            headermap.put(key, value);
        }

        //String simpleName = joinPoint.getTarget().getClass().getSimpleName();
        String methodName = joinPoint.getSignature().getName()+"";

        MethodSignature methodSignature =(MethodSignature) joinPoint.getSignature();
        String[] parameterNames = methodSignature.getParameterNames();

        Object[] param = joinPoint.getArgs();
        StringBuffer str = new StringBuffer();
        str.append("调用方法参数:");
        if(parameterNames!=null){
            for(int i=0;i<param.length;i++)
            str.append(parameterNames[i]).append("=").append(param[i]);
        }




        if(methodName.equalsIgnoreCase("loginForWeb")){
            params.put("createuser",((Map)param[2]).get("username")+"");//操作用户
        }

        //获取切入点所在的方法
        Method pointmethod = methodSignature.getMethod();
        //获取操作
        OperateLog operation = pointmethod.getAnnotation(OperateLog.class);
        if ( null != operation) {
            params.put("opername",operation.name()+"");//操作名称
            params.put("opertype",operation.value()+"");//操作类型
            params.put("client_type",operation.type()+"");//设备类型
        }


        params.put("id", UUID.randomUUID().toString().replaceAll("-",""));//操作日志记录id

        params.put("class_method",joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName()+"");//操作类方法
        params.put("http_method",method);//方法类型
        params.put("http_url",url);//操作url
        params.put("http_params",queryString);//操作参数
        //params.put("http_body",str.toString());//操作body参数
        //params.put("http_header",headermap.toString());//操作header参数
        //params.put("content","");//操作内容

        params.put("createip",IpAdrressUtil.getIpAdrress(request));//ip地址
        params.put("createuser", ActiveUserUtils.getUserNameCn());//操作用户


        params.put("createdate",new Date());//日期
        params.put("memo","");//备注

        long start = System.currentTimeMillis();
        Object result = joinPoint.proceed();
        long end = System.currentTimeMillis();
        params.put("cost",end-start);//耗时

        proOperlogService.insert(params);

        return result;
    }

    /**
     * 配置异常通知
     *
     * @param joinPoint join point for advice
     * @param e exception
     */
    @AfterThrowing(pointcut = "logPointcut()", throwing = "e")
    public void logAfterThrowing(JoinPoint joinPoint, Throwable e) {
        Map<String, Object> params = new HashMap<String, Object>();

        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = ((ServletRequestAttributes)requestAttributes).getRequest();
        String url = request.getRequestURL().toString();
        String method = request.getMethod();
        String uri = request.getRequestURI();
        String queryString = request.getQueryString();
        Map<String, String> headermap = new HashMap<String, String>();
        Enumeration<String> headerNames = request.getHeaderNames();
        while (headerNames.hasMoreElements()) {
            String key = (String) headerNames.nextElement();
            // 排除Cookie字段
            if (key.equalsIgnoreCase("Cookie")) {
                continue;
            }
            String value = request.getHeader(key);
            headermap.put(key, value);
        }

        //String simpleName = joinPoint.getTarget().getClass().getSimpleName();
        String methodName = joinPoint.getSignature().getName();

        MethodSignature methodSignature =(MethodSignature) joinPoint.getSignature();
        String[] parameterNames = methodSignature.getParameterNames();

        Object[] param = joinPoint.getArgs();
        StringBuffer str = new StringBuffer();
        str.append("调用方法参数:");
        if(parameterNames!=null){
            for(int i=0;i<param.length;i++)
                str.append(parameterNames[i]).append("=").append(param[i]);
        }


 

        if(methodName.equalsIgnoreCase("loginForWeb")){
            params.put("createuser",((Map)param[2]).get("username"));//操作用户
        }

        //获取切入点所在的方法
        Method pointmethod = methodSignature.getMethod();
        //获取操作
        OperateLog operation = pointmethod.getAnnotation(OperateLog.class);
        if ( null != operation) {
            params.put("opername",operation.name());//操作名称
            params.put("opertype",operation.value());//操作类型
            params.put("client_type",operation.type());//设备类型
        }


        params.put("id", UUID.randomUUID().toString().replaceAll("-",""));//操作日志记录id

        params.put("class_method",joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName());//操作类方法
        params.put("http_method",method);//方法类型
        params.put("http_url",url);//操作url
        params.put("http_params",queryString);//操作参数
        //params.put("http_body",str.toString());//操作body参数
        //params.put("http_header",headermap.toString());//操作header参数
        //params.put("content",ThrowableUtil.getStackTrace(e));//操作内容
        params.put("cost",0);//耗时
        params.put("createip",IpAdrressUtil.getIpAdrress(request));//ip地址

        params.put("createdate",new Date());//日期
        params.put("memo","");//备注

        proOperlogService.insert(params);
    }
}