package com.bohuikeji.frame.module.admin.component;


import com.alibaba.fastjson.JSON;
import com.bohuikeji.frame.module.admin.annotation.InitLog;
import com.bohuikeji.frame.module.admin.entity.back.APIEntity;
import com.bohuikeji.frame.module.admin.entity.sys.SysLog;
import com.bohuikeji.frame.module.admin.entity.sys.SysMenu;
import com.bohuikeji.frame.module.admin.entity.sys.SysUser;
import com.bohuikeji.frame.module.admin.service.ISysLogService;
import com.bohuikeji.frame.module.admin.utils.LocalHostUtil;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
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.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.lang.reflect.Method;

/**
 * 业务日志记录
 */
@Aspect
@Component
@Slf4j
public class LogComponent {

    @Autowired
    private ISysLogService logService;

    @Value("${server.port}")
    private int serverPort;

    //表示匹配带有自定义注解的方法
    @Pointcut("@annotation(com.bohuikeji.frame.module.admin.annotation.InitLog)")
    public void pointcut() {}

    @Around("pointcut()")
    public Object around(ProceedingJoinPoint point) throws Throwable {
        Object result =null;
        long beginTime = System.currentTimeMillis();

        SysLog sysLog=initLog(point);
        result = point.proceed();
        if(result instanceof APIEntity){
            APIEntity res=(APIEntity)result;
            if(res.getStatus()!=200){
                sysLog.setLogResult("失败");
                sysLog.setLogDetail(res.getMessage());
            }
        }
        sysLog.setLogReturn(JSON.toJSONString(result));
        long endTime = System.currentTimeMillis();
        sysLog.setRunTime(endTime-beginTime+"ms");
        logService.save(sysLog);
        return result;
    }

    private SysLog initLog(ProceedingJoinPoint point) {
        MethodSignature signature = (MethodSignature)point.getSignature();
        Method method = signature.getMethod();
        SysLog sysLog=new SysLog();
        InitLog initLog = method.getAnnotation(InitLog.class);
        if (initLog != null) {
            // 注解上的描述
            sysLog.setLogName(initLog.value());
            sysLog.setLogAction(initLog.action());
        }
        // 请求的类名
        String className = point.getTarget().getClass().getName();
        // 请求的方法名
        String methodName = signature.getName();
        //获取RequestAttributes
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        //从获取RequestAttributes中获取HttpServletRequest的信息
        HttpServletRequest request = (HttpServletRequest) requestAttributes.resolveReference(RequestAttributes.REFERENCE_REQUEST);
        HttpSession session= (HttpSession) requestAttributes.resolveReference(RequestAttributes.REFERENCE_SESSION);
        sysLog.setLogIp(request.getHeader("X-real-ip"));
        SysUser user=(SysUser)session.getAttribute("loginUser");
        if(user!=null){
            sysLog.setLogUser(user.getUserId());
        }
        sysLog.setLogNode(LocalHostUtil.getHostName()+":"+serverPort);
        sysLog.setLogType("操作日志");
        sysLog.setLogMethod(className+"."+methodName);
        sysLog.setLogParams(argsFormat(point.getArgs()));
        sysLog.setLogResult("成功");
        SysMenu menu=((SysMenu)session.getAttribute("activeMenu"));
        if(menu!=null){
            sysLog.setLogMenu(menu.getName());
            sysLog.setLogModel(menu.getName());
            SysMenu superMenu=menu.getSuperMenu();
            if(superMenu!=null){
                sysLog.setLogModel(superMenu.getName());
            }
        }
        sysLog.setLogUrl(request.getRequestURI());
        //放入Request
        request.setAttribute("sys_log",sysLog);
        return sysLog;
    }
    private String argsFormat(Object... args){
        if (args == null)
            return "null";

        int iMax = args.length - 1;
        if (iMax == -1)
            return "[]";
        StringBuilder b=new StringBuilder();
        b.append('[');
        for (int i = 0; ; i++) {
            if(args[i] instanceof HttpServletRequest){
                continue;
            }
            b.append(String.valueOf(args[i]));
            if (i == iMax)
                return b.append(']').toString();
            b.append(", ");
        }
    }
}
