package com.kym.admin.aspect;

import cn.dev33.satoken.stp.StpUtil;
import com.alibaba.fastjson2.JSON;
import com.kym.common.annotation.SysLog;
import com.kym.common.utils.HttpContextUtils;
import com.kym.common.utils.IDGenerator;
import com.kym.common.utils.IPUtils;
import com.kym.entity.SystemLog;
import com.kym.service.SystemLogService;
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.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;


/**
 * 系统日志，切面处理类
 *
 * @author skyline
 */
@Aspect
@Component
public class SysLogAspect {

    private static final Logger LOGGER = LoggerFactory.getLogger(SysLogAspect.class);
    private final SystemLogService systemLogService;
    IDGenerator idGenerator;

    SysLogAspect(SystemLogService systemLogService) {
        this.idGenerator = new IDGenerator();
        this.systemLogService = systemLogService;
    }

    /**
     * 切点
     */
    @Pointcut("@annotation(com.kym.common.annotation.SysLog)")
    public void logPointCut() {
    }

    @Around("logPointCut()")
    Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
        var startTime = System.currentTimeMillis();
        Object result = joinPoint.proceed();
        var executeTime = System.currentTimeMillis() - startTime;
        saveSysLog(joinPoint, executeTime);
        return result;
    }


    private void saveSysLog(ProceedingJoinPoint joinPoint, long executeTime) {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();

        SystemLog systemLog = new SystemLog();
        systemLog.setId(idGenerator.nextId());
        SysLog syslog = method.getAnnotation(SysLog.class);
        if (syslog != null) {
            //注解上的描述
            systemLog.setOperation(syslog.value());
        }

        //请求的方法名
        String className = joinPoint.getTarget().getClass().getName();
        String methodName = signature.getName();
        systemLog.setMethod(className + "." + methodName + "()");
        //请求的参数
        Object[] args = joinPoint.getArgs();

        if (!syslog.ignoreParams()) {
            String params = JSON.toJSON(args).toString();
            systemLog.setRequestParam(params);
        }

        //获取request
        HttpServletRequest request = HttpContextUtils.getHttpServletRequest();
        //设置IP地址
        systemLog.setIp(IPUtils.getIpAddr(request));
        //用户名、公司id、后台用户id（登录失败时无会话，跳过）
        if (StpUtil.isLogin()) {
            systemLog.setUserId(StpUtil.getSession().getLong("userId"));
            systemLog.setCompanyId(StpUtil.getSession().getLong("companyId"));
            systemLog.setUsername(StpUtil.getSession().getString("mobilePhone"));
        }
        systemLog.setExecuteTime(executeTime);

        //保存系统日志
        systemLogService.save(systemLog);
    }


}
