package com.simuwang.deploy.components;

import cn.hutool.core.exceptions.ExceptionUtil;
import com.simuwang.base.common.util.ServletUtils;
import com.smppw.common.pojo.ResultVo;
import jakarta.servlet.http.HttpServletRequest;
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.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class ApiAop {
    private static final String controller = "org.springframework.stereotype.Controller";
    private static final String deleteMapping = "org.springframework.web.bind.annotation.DeleteMapping";
    private static final String getMapping = "org.springframework.web.bind.annotation.GetMapping";
    private static final String patchMapping = "org.springframework.web.bind.annotation.PatchMapping";
    private static final String postMapping = "org.springframework.web.bind.annotation.PostMapping";
    private static final String putMapping = "org.springframework.web.bind.annotation.PutMapping";
    private static final String requestMapping = "org.springframework.web.bind.annotation.RequestMapping";
    private static final String restController = "org.springframework.web.bind.annotation.RestController";
    private static final String REQUEST_METHODS = " @annotation(" + getMapping + ") || @annotation(" + postMapping
            + ") || @annotation(" + requestMapping + ") || @annotation(" + deleteMapping + ") || @annotation("
            + putMapping + ") || @annotation(" + patchMapping + ") ";
    private static final String AOP = "(@within(" + restController + ") && (" + REQUEST_METHODS + ")) || (@within("
            + controller + ") && ( " + REQUEST_METHODS + "))";
    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Pointcut(AOP)
    public void pointcut() {
    }

    @Around("pointcut()")
    public Object spentTime(ProceedingJoinPoint thisJoinPoint) throws Throwable {
        HttpServletRequest request = ServletUtils.getRequest();
        String url = request.getServletPath();
        Object[] args = thisJoinPoint.getArgs();
        if (this.logger.isInfoEnabled()) {
            this.logger.info("接口{} 请求参数{} 开始请求", url, getArgsStr(url, args));
        }

        long start = System.currentTimeMillis();
        Object obj = thisJoinPoint.proceed(args);

        if (this.logger.isInfoEnabled()) {
            this.logger.info("接口{} 请求结束，耗时{} ms", url, (System.currentTimeMillis() - start));
        }
        if (null == obj) {
            return ResultVo.ok(null);
        }
        return obj;
    }

    private String getArgsStr(String url, Object[] args) {
        if (args != null) {
            StringBuilder str = new StringBuilder();
            try {
                for (Object o : args) {
                    if (o == null) {
                        continue;
                    }
                    String name = o.getClass().getSimpleName();
                    String data = o.toString();
                    str.append(", ").append(data).append("(").append(name).append(")");
                }
                return str.toString().replaceFirst(",", "");
            } catch (Exception e) {
                logger.warn("解析接口{} 参数异常\n{}", url, ExceptionUtil.stacktraceToString(e));
            }
        }
        return null;
    }
}
