package com.lantone.security.aop;

import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.lantone.common.dto.AbnormalLogDTO;
import com.lantone.common.dto.OperationLogDTO;
import com.lantone.common.util.HttpUtils;
import com.lantone.common.util.IpUtils;
import com.lantone.common.util.SysUserUtils;
import com.lantone.security.client.MessageService;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
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.Pointcut;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.Map;

/**
 * @Description:日志记录处理
 * @Author: cy
 * @time: 2021/9/5 17:18
 */

@Aspect
@Component
public class LogAspect {
    @Autowired
    private MessageService messageService;

    // 操作配置织入点
    @Pointcut("execution(public * com.lantone.security.web.DataAuthManagementController.*(..))"+
     "||execution(public * com.lantone.security.web.DictionaryManagementController.*(..))"+
     "||execution(public * com.lantone.security.web.FuncManagementController.*(..))"+
     "||execution(public * com.lantone.security.web.HospitalManagementController.*(..))"+
     "||execution(public * com.lantone.security.web.HospitalSetManagementController.*(..))"+
//     "||execution(public * com.lantone.security.web.LogManagementController.*(..))" +
//     "&& !execution(public * com.lantone.security.web.LogManagementController.getOperationLog(..))"+
     "||execution(public * com.lantone.security.web.RegionManagementController.*(..))"+
     "||execution(public * com.lantone.security.web.RoleManagementController.*(..))"+
     "||execution(public * com.lantone.security.web.UserManagementController.*(..))"+
     "&& !execution(public * com.lantone.security.web.UserManagementController.login(..))"+
     "&& !execution(public * com.lantone.security.web.UserManagementController.loadUserByUsername(..))"
    )
    public void operPointCut() {
    }

    // 异常配置织入点
    @Pointcut("execution(public * com.lantone.security.web.*.*(..))")
    public void errorPointCut() {
    }

    /**
     * 拦截异常操作
     *
     * @param joinPoint 切点
     * @param e         异常
     */
    @AfterThrowing(value = "errorPointCut()", throwing = "e")
    public void errorAfterThrowing(JoinPoint joinPoint, Exception e) {
        errorLog(joinPoint, e);
    }

    /**
     * 操作后执行
     *
     * @param
     */
    @AfterReturning(pointcut = "operPointCut()", returning = "jsonResult")
    public void operAfterReturning(JoinPoint joinPoint, Object jsonResult) {
        operLog(joinPoint, jsonResult);
    }

    /**
     * @Description: 操作日志记录
     * @Param: [joinPoint, jsonResult]
     * @return: void
     * @Author: cy
     * @Date: 2021/9/2
     */
    protected void operLog(JoinPoint joinPoint, Object jsonResult) {
        OperationLogDTO operationLog = multiplexing(joinPoint);
        // 返回参数
        if (null != jsonResult) {
            ObjectMapper objectWriter = new ObjectMapper();
            try {
                operationLog.setJsonResult(StringUtils.substring(objectWriter.writeValueAsString(jsonResult), 0, 150));
            } catch (JsonProcessingException e) {
                e.printStackTrace();
            }
        }
        messageService.operationLogHandle(operationLog);
    }


    /**
     * @Description: 异常日志记录
     * @Param: [joinPoint, jsonResult]
     * @return: void
     * @Author: cy
     * @Date: 2021/9/2
     */
    protected void errorLog(JoinPoint joinPoint, Exception e) {
        AbnormalLogDTO abnormalLogDTO = new AbnormalLogDTO();
        OperationLogDTO operationLog = multiplexing(joinPoint);
        BeanUtils.copyProperties(operationLog, abnormalLogDTO);
        abnormalLogDTO.setOperationAgent(HttpUtils.getHttpServletRequest().getHeader("User-Agent"));
        abnormalLogDTO.setOperationErrorInfo(StringUtils.substring(e.toString(), 0, 150));
        messageService.abnormalLogHandle(abnormalLogDTO);
    }

    /**
     * @Description: 返回信息相同日志代码复用
     * @Param: [joinPoint]
     * @return: com.lantone.common.dto.OperationLogDTO
     * @Author: cy
     * @Date: 2021/9/5
     */
    public OperationLogDTO multiplexing(JoinPoint joinPoint) {
        OperationLogDTO operationLog = new OperationLogDTO();
        Date date = new Date();
        operationLog.setOperationDate(date);
        operationLog.setGmtCreate(date);
        operationLog.setOperationId(SysUserUtils.getCurrentPrincipleId());
        operationLog.setOperationName(SysUserUtils.getCurrentPrinciple());
        String ip = HttpUtils.getIpAddress();
       if(IpUtils.isIPv4LiteralAddress(ip)){
           operationLog.setOperationIp(ip);
       }else{
           operationLog.setRemark("[非ipv4地址]:"+ip);
       }

        // 设置方法名称
        String className = joinPoint.getTarget().getClass().getName();
        String methodName = joinPoint.getSignature().getName();
        operationLog.setOperationMethod(className + "." + methodName + "()");
        // 设置请求方式
        operationLog.setOperationWay(HttpUtils.getHttpServletRequest().getMethod());
        operationLog.setOperationUrl(HttpUtils.getHttpServletRequest().getRequestURI());
        // 处理设置注解上的参数
        try {
            String params = getControllerMethodDescription(joinPoint);
            if (StringUtils.isNotBlank(params)) {
                operationLog.setOperationParam(params);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return operationLog;
    }

    /**
     * @Description:获取请求的参数
     * @Param: [joinPoint, logInformation]
     * @return: void
     * @Author: cy
     * @Date: 2021/9/2
     */
    private String getControllerMethodDescription(JoinPoint joinPoint) throws Exception {
        Map<String, String[]> map = HttpUtils.getHttpServletRequest().getParameterMap();
        if (MapUtils.isNotEmpty(map)) {
            String params = JSONObject.toJSONString(map);
            return params;
        } else {
            Object args = joinPoint.getArgs();
            if (null != args) {
                String params = argsArrayToString(joinPoint.getArgs());
                return StringUtils.substring(params, 0, 150);
            }
        }
        return "";
    }


    /**
     * 参数拼装
     *
     * @Description:
     * @Param: [paramsArray]
     * @return: java.lang.String
     * @Author: cy
     * @Date: 2021/9/2
     */
    private String argsArrayToString(Object[] paramsArray) {
        String params = "";
        if (paramsArray != null && paramsArray.length > 0) {
            for (int i = 0; i < paramsArray.length; i++) {
                if (null != (paramsArray[i])) {
                    Object jsonObj = JSONObject.toJSONString(paramsArray[i]);
                    params += jsonObj.toString() + " ";
                }
            }
        }
        return params.trim();
    }
}


