package com.rf.psychological.opLog.aspect;

import com.alibaba.fastjson.JSONObject;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.rf.psychological.opLog.annotation.OperationLogAnnotation;
import com.rf.psychological.opLog.dao.SysLogEntity;
import com.rf.psychological.opLog.service.SysLogService;
import com.rf.psychological.utils.DateUtil;
import com.rf.psychological.utils.IPUtiles;
import com.rf.psychological.utils.JWTUtil;
import com.rf.psychological.utils.Result;
import com.rf.psychological.institution.model.InstitutionEntity;
import com.rf.psychological.institution.model.InstitutionUserEntity;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
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 org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;

/**
 * @author lpf
 * @description:
 * @date 2021/12/2515:24
 */
@Aspect
@Component
public class UserLogAspect {

    private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    @Autowired
    private SysLogService sysLogService;

    @Pointcut("@annotation(com.rf.psychological.opLog.annotation.OperationLogAnnotation)")
    public void logPointCut() {
    }

    @AfterReturning(returning = "result", value = "logPointCut()")
    public void saveOpLog(JoinPoint joinPoint, Object result) {
        // 获取RequestAttributes
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        // 从获取RequestAttributes中获取HttpServletRequest的信息
        HttpServletRequest request = (HttpServletRequest) requestAttributes.resolveReference(RequestAttributes.REFERENCE_REQUEST);

        //从切面织入点处通过反射机制获取织入点处的方法
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        //获得切入点方法
        Method method = signature.getMethod();
        //通过方法获取所在类
        Class<?> aClass = method.getDeclaringClass();
        Api classAnnotation = aClass.getAnnotation(Api.class);
//        //获取切入点参数
//        DefaultParameterNameDiscoverer defaultParameterNameDiscoverer = new DefaultParameterNameDiscoverer();
//        String[] parameterNames = defaultParameterNameDiscoverer.getParameterNames(method);
//        Object[] args = joinPoint.getArgs();
//        HashMap<String, Object> paramMap = new HashMap<>();
//        for (int i = 0; i < parameterNames.length; i++) {
//            paramMap.put(parameterNames[i], args[i]);
//        }
//        paramMap.forEach((key, value) -> {
//            System.out.println(key + ":" + value);
//        });
        Result returnResult = (Result) result;
        String value;
        OperationLogAnnotation opLogAnnotation = method.getAnnotation(OperationLogAnnotation.class);
        ApiOperation apiAnnotation = method.getAnnotation(ApiOperation.class);
        if (!opLogAnnotation.value().equals("")) {
            System.out.println("opLogAnnotation.value() ：" + opLogAnnotation.value());
            value = opLogAnnotation.value();
        } else {
            System.out.println("spAnnotation :" + apiAnnotation.value());
            value = apiAnnotation.value();
        }
        //获取类上apiOperation的数据
        //如果所在类的注解上有值则将此值与方法上的名称在一起组成，例如“用户操作-登录”
        if (!Arrays.toString(classAnnotation.tags()).equals("")) {
            value = Arrays.toString(classAnnotation.tags()) + "-" + value;
        }
        //获取方法名字
        String methodName = method.getName();
        //开始时间
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS");
        String beginTime = df.format(new Date());
        //获取当前时间
        Timestamp timestamp = Timestamp.valueOf(sdf.format(new Date()));
        System.out.println("timestamp" + timestamp);
        //获取ip
        String realIp = IPUtiles.getRealIp(request);
        System.out.println("realIp:" + realIp);
        //获取请求url
        String requestURI = request.getRequestURI();
        String userPhone = "";
        String userId = "";
        String petName = "";
        String institutionNo = "";
        String type = "";
        Boolean flag = false;
        //获取用户
        //如果是为登录操作，因为没有token所以不从token中获取
        if (!(requestURI.equals("/system/login") )) {
            String token = request.getHeader("Authorization");
            token = token.split(" ")[1];//以空格划分Bearer token，获取token
            System.out.println("-------------------------token-----------------------");
            System.out.println(token);
            //从请求头中获取token
            DecodedJWT verify = JWTUtil.verify(token);
            userPhone = verify.getClaim("userPhone").asString();
            userId = verify.getClaim("userId").asString();
            petName = verify.getClaim("petName").asString();
            institutionNo = verify.getClaim("institutionNo").asString();
            //获取此时操作的用户类型，分别是user，admin，superAdmin
            type = verify.getClaim("type").asString();
            flag = true;
        } else {
            //登录成功时候从返回值中获取，登录有问题不进行存储
            System.out.println(returnResult.getData());
            if (!returnResult.getData().equals("")) {
                JSONObject returnData = (JSONObject) returnResult.getData();
                userId = returnData.get("userId").toString();
                petName = returnData.get("petName").toString();
                institutionNo = returnData.get("institutionNo").toString();
                type = returnData.getString("type").toString();
                flag = true;
            }
        }
        if (flag) {
            //获取当前时间
            String endTime = df.format(new Date());
            SysLogEntity sysLogEntity = new SysLogEntity();
            sysLogEntity.setIp(realIp);
            sysLogEntity.setCreateTime(timestamp);
            sysLogEntity.setUserId(userId);
            sysLogEntity.setMethod(methodName);
            sysLogEntity.setOperation(value);
            sysLogEntity.setUserName(petName);
            sysLogEntity.setInstitutionNo(institutionNo);
            switch (type) {
                case "1":
                    type = "user";
                    break;
                case "2":
                    type = "admin";
                    break;
                case "3":
                    type = "superAdmin";
                    break;
                default:
                    type = "";
                    break;
            }
            sysLogEntity.setType(type);
            sysLogEntity.setUrl(requestURI);
            sysLogEntity.setResponseTime(DateUtil.getDistanceTime(beginTime,endTime));
            sysLogEntity.setResult(returnResult.getCode() + "/" + returnResult.getMsg());
            sysLogService.save(sysLogEntity);
        }
        System.out.println("result:  " + ((Result) result).getCode());
        System.out.println("result:  " + ((Result) result).getMsg());
        System.out.println("result:  " + ((Result) result).getData());
    }
}
