package cn.quantgroup.customer.aop;

import cn.quantgroup.customer.config.container.UserThreadLocal;
import cn.quantgroup.customer.constant.Constant;
import cn.quantgroup.customer.entity.OpUser;
import cn.quantgroup.customer.entity.OperateLogModel;
import cn.quantgroup.customer.service.IOperateLogService;
import cn.quantgroup.customer.util.DateUtil;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
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.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.Objects;

/**
 * @author yangjun
 * @Date 2020/4/14 13:33
 * @Desc
 * @Update
 */
@Aspect
@Component
@Slf4j
public class OperateLogAspect {

    @Autowired
    private IOperateLogService operateLogService;

    @Pointcut("@annotation(cn.quantgroup.customer.aop.OperateLog)")
    public void operateLog() {
    }


    @Around(value = "operateLog()")
    public Object around(ProceedingJoinPoint pjp) throws Throwable {
        String logPre = "OperateLogAspect.around";
        log.info("{} 进入切面", logPre);
        Object[] args = pjp.getArgs();
        log.info("{} 请求参数 {}", logPre, args);
        Object result = pjp.proceed(args);
        log.info("{} 请求参数 {},返回结果 {} ", logPre, args, result);
        addOperateLog(pjp, result);
        return result;

    }

    private void addOperateLog(ProceedingJoinPoint pjp, Object result) {
        String logPre = "OperateLogAspect.addOperateLog";
        Object[] args = pjp.getArgs();
        StringBuffer reqStrBuffer = new StringBuffer();


        Long loanId = null;
        String applyNo = null;
        String remark = null;
        String opState = "";
        for (Object obj : args) {
            reqStrBuffer.append(String.valueOf(obj));
            try {
                JSONObject jsonObject = JSONObject.parseObject(JSONObject.toJSONString(obj));
                if (Objects.nonNull(jsonObject)) {
                    if (jsonObject.containsKey("loanId")) {
                        loanId = jsonObject.getLong("loanId");
                    }

                    if (jsonObject.containsKey("applyNo")) {
                        applyNo = jsonObject.getString("applyNo");
                    }

                    if (jsonObject.containsKey("remark")) {
                        remark = jsonObject.getString("remark");
                    }

                    if (jsonObject.containsKey("remark")) {
                        remark = jsonObject.getString("remark");
                    }

                    if (jsonObject.containsKey("opState")) {
                        Integer opStateFlag = jsonObject.getInteger("opState");
                        if(opStateFlag == 1){
                            opState = "添加白名单";
                        }else{
                            opState = "移除白名单";
                        }
                    }

                }
            } catch (Exception e) {
                log.warn("{} obj={} 转化json失败", logPre, obj);
            }
        }
        MethodSignature methodSignature = (MethodSignature) pjp.getSignature();
        Method method = methodSignature.getMethod();
        OperateLog operateLog = method.getAnnotation(OperateLog.class);
        log.info("{} 获得注解 operateLog={}", logPre, operateLog);
        String className = pjp.getTarget().getClass().getName().substring(pjp.getTarget().getClass().getName().lastIndexOf(".") + 1);
        String methodName = method.getName();
        String moduleName = operateLog.moduleName();
        String module = className.concat("|").concat(methodName);
        if (StringUtils.isBlank(moduleName)) {
            // 类名 + 方法签名为  moduleName
            moduleName = module;
        }

        // 针对特殊情形，需要取不同操作
        if(StringUtils.isNotBlank(opState)){
            moduleName = opState;
        }

        log.info("{} 处理结果:{}", logPre, String.valueOf(result));
        JSONObject resultJson = JSONObject.parseObject(JSONObject.toJSONString(result));
        int status = 0;
        if(resultJson.containsKey("code") && Constant.SUCCESS_CODE.equals(resultJson.getString("code"))){
            status = 1;
        }

        OpUser opUser = UserThreadLocal.get();
        OperateLogModel model = OperateLogModel.builder()
                .userName(opUser.getName())
                .userNo(opUser.getUser())
                .module(module)
                .moduleName(moduleName)
                .request(reqStrBuffer.toString())
                .response(String.valueOf(result))
                .createdAt(DateUtil.getCurrentTimestamp())
                .loanId(loanId)
                .applyNo(applyNo)
                .remark(remark)
                .status(status)
                .build();

        operateLogService.saveOperateLog(model);
        // 防止内存泄漏
        UserThreadLocal.remove();
    }


}
