/*
 * Copyright (c) 京北方信息技术股份有限公司 Corporation 2021 . All rights reserved.
 *
 */
package net.northking.cctp.common.log;

import com.alibaba.fastjson.JSON;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.hzbank.testteam.autotest.dependencies.authDependency.constants.AuthDependencyConstants;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;
import java.util.Objects;

/**
 * Http日志切面
 *
 * @author : xiusong.xie
 * @version : 1.0
 */
@Slf4j
@Aspect
@Component
public class HttpLogAspect
{
  /**
   * 日志
   */
  private final static Logger logger = LoggerFactory.getLogger(HttpLogAspect.class);

  private final static int MAX_LENGTH = 2000;
  /**
   * 微服务名称
   */
  @Value("${spring.application.name}")
  private String appName;

  /**
   * 当前节点的IP地址
   */
  @Value("${spring.cloud.client.ip-address}")
  private String host;

  /**
   * 当前节点的端口
   */
  @Value("${server.port}")
  private int port;

  @Autowired
  private ObjectMapper objectMapper;

  @Autowired
  private HttpLogProducer httpLogProducer;

  /**
   * 记录http GET 请求
   *
   * @param point 切入点
   */
  @Around("@annotation(org.springframework.web.bind.annotation.GetMapping)")
  public Object logGET(ProceedingJoinPoint point) throws Throwable
  {
    return logHttpTrace(point);
  }

  /**
   * 记录http POST 请求
   *
   * @param point 切入点
   */
  @Around("@annotation(org.springframework.web.bind.annotation.PostMapping)")
  public Object logPOST(ProceedingJoinPoint point) throws Throwable
  {
    return logHttpTrace(point);
  }

  /**
   * 记录http PUT 请求
   *
   * @param point 切入点
   */
  @Around("@annotation(org.springframework.web.bind.annotation.PutMapping)")
  public Object logPUT(ProceedingJoinPoint point) throws Throwable
  {
    return logHttpTrace(point);
  }

  /**
   * 记录http DELETE 请求
   *
   * @param point 切入点
   */
  @Around("@annotation(org.springframework.web.bind.annotation.DeleteMapping)")
  public Object logDELETE(ProceedingJoinPoint point) throws Throwable {
    return logHttpTrace(point);
  }

  private Object logHttpTrace(ProceedingJoinPoint point) throws Throwable {
    httpLogPrint(point);
    Object result = null;
    try {
      result = point.proceed();
      return result;
    } finally {
      String retData = "";
      try {
        retData = JSON.toJSONString(result);
      } catch (Exception e) {
        retData = result != null ? result.toString().substring(0, Math.min(result.toString().length(), MAX_LENGTH)) : null;
      }
      String methodName = "";
      try {
        methodName = point.getSignature().getName();
      } catch (Exception e) {
        //不处理
      }
      logger.info(methodName + "接口返回参数：" + retData);
    }
  }


  /**
   * 打印日志
   *
   * @param proceedingJoinPoint 切入点
   * @return http日志对象
   */
  private void httpLogPrint(ProceedingJoinPoint proceedingJoinPoint) {

    try {
      // 请求开始时间
      long startTime = System.currentTimeMillis();
      // 请求映射控制类
      String clazzName = proceedingJoinPoint.getTarget().getClass().getSimpleName();
      // 请求方法
      String methodName = proceedingJoinPoint.getSignature().getName();
      // 请求用户
      HttpServletRequest request = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
      String userName = (String) request.getAttribute("userName");
      if (userName == null) {
        userName = "";
      }
      Object[] args = proceedingJoinPoint.getArgs();
      String params = "";
      try{
        params = JSON.toJSONString(args);
      }catch (Exception e){
        params = args != null ? Arrays.toString(args).substring(0,Math.min(MAX_LENGTH, Arrays.toString(args).length())) : null;
      }
      String requestUserIdString = request.getHeader(AuthDependencyConstants.REQUEST_HEADER_USER_ID);
      Long requestUserId = null;
      if (!StringUtils.isEmpty(requestUserIdString)) {
        requestUserId = Long.valueOf(requestUserIdString);
      }
      log.info("请求结束，请求映射控制类：【{}】，请求方法：【{}】，请求耗时：【{}毫秒】，请求用户：【{}】，请求用户Id：【{}】，请求参数:{}",
              clazzName, methodName, System.currentTimeMillis() - startTime, userName, requestUserId, params);
    } catch (Exception e) {
      log.error("打印http参数失败！"+e);
    }

  }


}
