package com.xjrsoft.common.aspect;

import cn.dev33.satoken.session.SaSession;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.extra.servlet.ServletUtil;
import com.google.gson.Gson;
import com.xjrsoft.common.annotation.XjrLog;
import com.xjrsoft.common.constant.GlobalConstant;
import com.xjrsoft.common.enums.LogCategoryEnum;
import com.xjrsoft.common.utils.HttpContextUtils;
import com.xjrsoft.module.organization.entity.User;
import com.xjrsoft.module.system.entity.Log;
import com.xjrsoft.module.system.mapper.LogMapper;
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.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.time.LocalDateTime;


/**
 * 日志切面
 *
 * @author tzx
 */
@Aspect
@Component
public class XjrLogAspect {

	@Autowired
	private LogMapper logMapper;

	
	@Pointcut("@annotation(com.xjrsoft.common.annotation.XjrLog)")
	public void logPointCut() { 
		
	}


	@Around("logPointCut()")
	public Object around(ProceedingJoinPoint point) throws Throwable {
		long beginTime = System.currentTimeMillis();
		Object result = null;
		try {
			//执行方法
			result = point.proceed();
		} catch (Throwable e) {
			//执行时长(毫秒)
			long time = System.currentTimeMillis() - beginTime;
			insertLog(point, time, LogCategoryEnum.EXCEPTION.getCode());
			throw e;
		}
		//执行时长(毫秒)
		long time = System.currentTimeMillis() - beginTime;

		//保存日志
		insertLog(point, time, null);

		return result;
	}

	private void insertLog(ProceedingJoinPoint joinPoint, long time, Integer category) {
		MethodSignature signature = (MethodSignature) joinPoint.getSignature();
		Method method = signature.getMethod();

		Log logEntity = new Log();
		XjrLog xjrLog = method.getAnnotation(XjrLog.class);
		if(xjrLog != null){
			//注解上的描述
			logEntity.setOperation(xjrLog.value());
		}

		//请求的方法名
		String className = joinPoint.getTarget().getClass().getName();
		String methodName = signature.getName();
		logEntity.setMethod(className + "." + methodName + "()");

		//请求的参数
		Object[] args = joinPoint.getArgs();
		try{
			String params = new Gson().toJson(args);
			if (params.length() < 4000) {
				logEntity.setParams(params);
			}
		}catch (Exception e){

		}

		//获取request
		HttpServletRequest request = HttpContextUtils.getHttpServletRequest();
		//设置IP地址
		logEntity.setIp(ServletUtil.getClientIP(request));

		//用户名
		//判断是否已登录，如果已登录了，就获取token时间，未登录状态直接放行
		if(StpUtil.isLogin()){
			SaSession tokenSession = StpUtil.getTokenSession();
			User user = tokenSession.get(GlobalConstant.LOGIN_USER_INFO_KEY, new User());
			logEntity.setUsername(user.getUserName());
			logEntity.setTime(time);
			logEntity.setCategory(category == null ? getCategory(request) : category);
			logEntity.setCreateTime(LocalDateTime.now());
			//保存系统日志
			logMapper.insert(logEntity);
		}
	}

	/**
	 * @title 获取日志分类
	 * @create 2020年11月11日 19:23:30
	 * */
	private int getCategory(HttpServletRequest request){
		if(request.getRequestURI().equalsIgnoreCase("/system/login")){
			return LogCategoryEnum.LOGIN.getCode();
		}
		else if (request.getMethod().toLowerCase().equals("get")){
			return  LogCategoryEnum.GET.getCode();
		}
		else if(request.getMethod().toLowerCase().equals("post") || request.getMethod().toLowerCase().equals("put") || request.getMethod().toLowerCase().equals("patch") || request.getMethod().toLowerCase().equals("delete")) {
			return  LogCategoryEnum.OPERAT.getCode();
		}
		else
			return  LogCategoryEnum.EXCEPTION.getCode();
	}
}
