package com.limap;

import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSONObject;
import com.limap.common.utils.MailUtils;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

/**
 *

 * 使用 aop 切面记录请求日志信息
 *
 * @author jjb
 * @since 2021-11-09
 */
@Aspect
@Component
@Slf4j
public class AopLog {

    private static final String START_TIME = "request-start";

    /**
     * 切入点
     */
    @Pointcut("execution(* com.limap.work.controller.app..*(..))")
    public void log() {


    }

    /**
     * 前置操作
     *
     * @param point 切入点
     */
    @Before("log()")
    public void beforeLog(JoinPoint point) {

        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();

        HttpServletRequest request = Objects.requireNonNull(attributes).getRequest();

        log.info("【请求 URL】：{}", request.getRequestURL());
        log.info("【请求 IP】：{}", request.getRemoteAddr());
        log.info("【请求类名】：{}，【请求方法名】：{}", point.getSignature().getDeclaringTypeName(), point.getSignature().getName());

        Map<String, String[]> parameterMap = request.getParameterMap();
        log.info("【请求参数】：{},", JSONObject.toJSONString(parameterMap));
        Long start = System.currentTimeMillis();
        request.setAttribute(START_TIME, start);
    }

    /**
     * 环绕操作
     *
     * @param point 切入点
     * @return 原方法返回值
     * @throws Throwable 异常信息
     */
    @Around("log()")
    public Object aroundLog(ProceedingJoinPoint point) throws Throwable {

        Object result = point.proceed();
        log.info("【返回值】：{}", JSONUtil.toJsonStr(result));
        //返回数据给切面方法
        return result;
    }

    /**
     * 异常通知操作 (看情况是否需要,一般项目都有全局异常处理)
     *
     * @param point 切入点
     */
    @AfterThrowing(value = "log()",throwing = "e")
    public void afterThrowingLog(JoinPoint point,Exception e) {

        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();

        HttpServletRequest request = Objects.requireNonNull(attributes).getRequest();

        log.info("【异常请求 URL】：{}", request.getRequestURL());
        log.info("【异常请求 IP】：{}", request.getRemoteAddr());
        log.info("【异常请求类名】：{}，【请求方法名】：{}", point.getSignature().getDeclaringTypeName(), point.getSignature().getName());

        Map<String, String[]> parameterMap = request.getParameterMap();
        log.info("【异常请求参数】：{}，", JSONObject.toJSONString(parameterMap));
        log.info("【异常信息】：{}，", JSONUtil.toJsonStr(e.getMessage()));

        Map<String,Object> map = new HashMap<>();
        Map<String,Object> params = new HashMap<String,Object>(){{
            put("异常请求 URL",request.getRequestURL());
            put("异常请求 IP",request.getRemoteAddr());
            put("异常请求参数",JSONObject.toJSONString(parameterMap));
            put("异常信息",JSONUtil.toJsonStr(e.getMessage()));
        }};
//        map.put("host","smtp.163.com");
////        map.put("mailFrom","17863938131@163.com");
//        map.put("mailFrom","18453076019@163.com");
////        map.put("passwd","DPVROHZZPETWTCDV");
//        map.put("passwd","EEZGZODVTOLFLHWR");
//        map.put("host","smtp.qq.com");
//        map.put("mailFrom","251173110@qq.com");
//        map.put("fromUser","小叮塘助手");
//        map.put("passwd","fqxusebzierbbgha");
//        map.put("mailTo","31320887171@qq.com");
////        map.put("mailTo","623044253@qq.com,niuwj@qdlimap.com");
//        //标题和内容配置
//        map.put("mailTittle","小叮塘助手系统异常提示");
//        map.put("mailContent",JSONObject.toJSONString(params));
//        //发送简单邮件
//        MailUtils.sendSimpleMail(map);
    }

    /**
     * 后置操作
     */
    @AfterReturning("log()")
    public void afterReturning() {

        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = Objects.requireNonNull(attributes).getRequest();

        Long start = (Long) request.getAttribute(START_TIME);
        Long end = System.currentTimeMillis();
        log.info("【请求耗时】：{}毫秒", end - start);
    }
}
