package com.zksy.data.annotation;

import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.StrUtil;
import com.zksy.data.domain.po.XhDataLog;
import com.zksy.data.mapper.XhDataLogMapper;
import com.zksy.data.service.XhDataLogService;
import com.zksy.data.utils.PublisherMessage;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.Date;
import java.util.concurrent.CompletableFuture;

@Aspect
@Component
@Slf4j
public class XhLogAspect {
    @Autowired
    private XhDataLogService xhDataLogService;
    @Autowired
    private XhDataLogMapper xhDataLogMapper;
    @Autowired
    private RedisTemplate<String,String> redisTemplate;
    @Autowired
    private PublisherMessage publisherMessage;

    public void saveBeforeLog(XhDataLog xhDataLog) {
        xhDataLogMapper.insert(xhDataLog);
    }

    @Around("execution(* com.zksy.data.service.impl.*.*(..)) && @annotation(com.zksy.data.annotation.XhDataLogRecord)")
    public void log(ProceedingJoinPoint joinPoint) throws Throwable {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        XhDataLogRecord XhDataLogRecord = method.getAnnotation(XhDataLogRecord.class);
        XhDataLog xhDataLog = new XhDataLog();
        String id = UUID.randomUUID().toString(true);
        xhDataLog.setId(id);
        String firstParam = "";
        if (XhDataLogRecord != null) {
            xhDataLog.setBusinessName(XhDataLogRecord.value());
            StringBuilder sb = new StringBuilder();
            Object[] args = joinPoint.getArgs();
            for (int i = 0; i < args.length; i++) {
                if(i == 0){
                    firstParam = args[i].toString();
                }
                sb.append("参数 ").append(i).append(": ").append(args[i]).append("\n");
            }
            xhDataLog.setParams(sb.toString());
        }
        xhDataLog.setIsRunning(1);
        xhDataLog.setCreateTime(new Date());

        CompletableFuture.runAsync(() -> {
            saveBeforeLog(xhDataLog);
            publisherMessage.emitDelayMessage(id,7200000);
        });
        try {
            joinPoint.proceed();
            xhDataLog.setIsSuccess(1);
        } catch (Exception e) {
            xhDataLog.setIsSuccess(0);
            xhDataLog.setException(e.getMessage());
            if(StrUtil.isNotBlank(firstParam)){
                redisTemplate.opsForValue().set(firstParam,id);
            }
        } finally {
            xhDataLog.setIsRunning(0);
            xhDataLog.setUseTime((int) (System.currentTimeMillis() - xhDataLog.getCreateTime().getTime()));
            xhDataLog.setUpdateTime(new Date());
            xhDataLogMapper.updateById(xhDataLog);
            Thread.sleep(20000);
            redisTemplate.delete(firstParam);
        }
    }
}
