package com.hzs.common.core.aspect;

import cn.hutool.json.JSONUtil;
import com.hzs.common.core.annotation.Log;
import com.hzs.common.core.context.SecurityContextHolder;
import com.hzs.common.core.utils.ServletUtils;
import com.hzs.common.core.utils.ip.IpUtils;
import com.hzs.common.domain.system.sys.SysOperationLog;
import com.hzs.system.sys.IOperationLogServiceApi;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;

/**
 * Description: 用户操作统一日志处理
 * Author: jiang chao
 * Time: 2022/9/14 14:15
 * Classname: OperationLogAspectAdvice
 * PackageName: com.hzs.common.core.aspect
 */
@Slf4j
@Aspect
@Component
public class OperationLogAspectAdvice {

    @DubboReference
    private IOperationLogServiceApi iOperationLogServiceApi;

    /**
     * 定义切点Pointcut
     */
    @Pointcut("execution(* com.hzs..controller.manage..*Controller.*(..)) || execution(* com.hzs..controller.manager..*Controller.*(..))")
    public void operationLogPointCut() {
    }

    /**
     * 执行返回时进行处理
     *
     * @param joinPoint
     * @return
     */
    @After(value = "operationLogPointCut()")
    public void operationLogPointAfter(JoinPoint joinPoint) {
        // 请求方法
        Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();
        // 日志注解
        Log logAnnotation = method.getAnnotation(Log.class);

        if (null != logAnnotation) {
            // 操作用户、操作时间、操作模块、操作方法、操作参数、IP地址
            SysOperationLog sysOperationLog = new SysOperationLog();
            sysOperationLog.setUserId(SecurityContextHolder.getUserId());
            sysOperationLog.setOperationModule(logAnnotation.module().getLabel());
            sysOperationLog.setOperationBusiness(logAnnotation.business().getLabel());
            sysOperationLog.setOperationMethod(logAnnotation.method().getLabel());
            sysOperationLog.setRemark(logAnnotation.remark());
            sysOperationLog.setPkCountry(SecurityContextHolder.getUserCountry());

            // TODO cabbage 参数处理，入参转中文
            String param = JSONUtil.toJsonStr(joinPoint.getArgs()).trim();
            sysOperationLog.setOperationParam(param);

            HttpServletRequest request = ServletUtils.getRequest();
            if (null != request) {
                sysOperationLog.setIpaddr(IpUtils.getIpAddr(request));
                sysOperationLog.setUri(request.getRequestURI());
            }

            log.info("操作日志记录： {}", sysOperationLog);
            iOperationLogServiceApi.saveOperationLog(sysOperationLog);
        }
    }

}
