package com.fjs.scenic.config;

import java.time.LocalDateTime;
import java.util.Date;

import javax.servlet.http.HttpServletRequest;

import com.fjs.scenic.annotation.LoggerManage;
import com.fjs.scenic.entity.system.Logs;
import com.fjs.scenic.service.system.impl.LogsService;
import com.fjs.scenic.utils.Cons;
import com.fjs.scenic.utils.ReturnResult;
import org.apache.log4j.Logger;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;


/**
 * 日志切面
 *
 **/
@Aspect
@Component
public class LoggerAdvice {
	
	@Autowired
	private LogsService logsService;
	
    private Logger logger = Logger.getLogger(this.getClass());

    @Before("within(com.fjs.scenic.controller..*) && @annotation(loggerManage)")
    public void addBeforeLogger(JoinPoint joinPoint, LoggerManage loggerManage) {
        LocalDateTime now = LocalDateTime.now();
        logger.info(now.toString()+"执行[" + loggerManage.logDescription() + "]开始");
        logger.info(joinPoint.getSignature().toString());
        logger.info(parseParames(joinPoint.getArgs()));

        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        Authentication auth = SecurityContextHolder.getContext().getAuthentication();

        HttpServletRequest request = attributes.getRequest();
        Logs logs = new Logs();
        logs.setIp(request.getRemoteAddr());
        logs.setType(Cons.LOGS_TYPE.GENERAL);
        logs.setTime(new Date());
        logs.setClassName(joinPoint.getSignature().toString());
        logs.setMethodName(loggerManage.logDescription());
        logs.setAccount(auth.getName());
        logs.setParams(parseParames(joinPoint.getArgs()));
        
        logsService.optionLogs(logs);

    }

    @AfterReturning("within(com.fjs.scenic.controller..*) && @annotation(loggerManage)")
    public void addAfterReturningLogger(JoinPoint joinPoint, LoggerManage loggerManage) {
        LocalDateTime now = LocalDateTime.now();
        logger.info(now.toString()+"执行 [" + loggerManage.logDescription() + "] 结束");
    }

    @AfterThrowing(pointcut = "within(com.fjs.scenic.controller..*) && @annotation(loggerManage)", throwing = "ex")
    public void addAfterThrowingLogger(JoinPoint joinPoint, LoggerManage loggerManage, Exception ex) {
        LocalDateTime now = LocalDateTime.now();
        logger.error(now.toString()+"执行 [" + loggerManage.logDescription() + "] 异常", ex);

        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        Authentication auth = SecurityContextHolder.getContext().getAuthentication();

        Logs logs = new Logs();
        logs.setIp(request.getRemoteAddr());
        logs.setType(Cons.LOGS_TYPE.GENERAL);
        logs.setTime(new Date());
        logs.setClassName(joinPoint.getSignature().toString());
        logs.setMethodName(loggerManage.logDescription());
        logs.setParams(parseParames(joinPoint.getArgs()));
        logs.setAccount(auth.getName());
        logs.setErrorMsg(ex.getMessage());
        logsService.optionLogs(logs);
    }

    private String parseParames(Object[] parames) {
        if (null == parames || parames.length <= 0) {
            return "";
        }
        StringBuffer param = new StringBuffer("传入参数 # 个:[ ");
        int i =0;
        for (Object obj : parames) {
            i++;
            if (i==1){
                param.append(obj.toString());
                continue;
            }
            param.append(" ,").append(obj.toString());
        }
        return param.append(" ]").toString().replace("#",String.valueOf(i));
    }


}