package com.njcn.common.utils;


import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ReflectUtil;
import com.njcn.common.pojo.annotation.OperateInfo;
import com.njcn.common.pojo.constant.LogInfo;
import com.njcn.common.pojo.constant.OperateType;
import com.njcn.common.pojo.enums.common.LogEnum;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;

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

/**
 * @author hongawen
 * @version 1.0.0
 * @date 2021年06月10日 13:32
 */
@Slf4j
public class ReflectCommonUtil {


    /**
     * 根据异常获取系统内controller中的方法
     * @param exception 运行时异常
     */
    public static Method getMethod(Exception exception) {
        List<String> stackInfo = ExceptionUtil.getFirstControllerAndMethodName(exception);
        Method method = null;
        if (!CollectionUtil.isEmpty(stackInfo)) {
            String controllerName = stackInfo.get(0);
            String methodName = stackInfo.get(1);
            try {
                method =ReflectUtil.getMethodByName(Class.forName(controllerName), methodName);
            } catch (ClassNotFoundException e) {
                log.error("根据controller名以及方法名反射获取方法体异常，controller为：{}，方法为：{}，异常为：{}", controllerName, methodName, e.getMessage());
            }
        }
        return method;
    }


    /**
     * 从异常堆栈信息里找出controller上@ApiOperation内容
     *
     * @param exception 异常
     */
    public static String getMethodDescribeByException(Exception exception) {
        List<String> stackInfo = ExceptionUtil.getFirstControllerAndMethodName(exception);
        String operate = LogInfo.UNKNOWN_OPERATE;
        if (!CollectionUtil.isEmpty(stackInfo)) {
            String controllerName = stackInfo.get(0);
            String methodName = stackInfo.get(1);
            try {
                operate = ReflectCommonUtil.getMethodDescribeByClassAndMethodName(Class.forName(controllerName), methodName);
            } catch (ClassNotFoundException e) {
                log.error("根据controller名以及方法名获取操作注解内容异常，controller为：{}，方法为：{}，异常为：{}", controllerName, methodName, e.getMessage());
            }
        }
        return operate;
    }

    /**
     * 获取controller上方法@ApiOperation注解的值，作为当前方法的简短描述
     */
    public static String getMethodDescribeByClassAndMethodName(Class<?> clazz, String methodName) {
        Method method = ReflectUtil.getMethodByName(clazz, methodName);
        return getMethodDescribeByMethod(method);
    }


    /**
     * 获取方法上@ApiOperation注解的值，作为当前方法的简短描述
     */
    public static String getMethodDescribeByMethod(Method method) {
        String operate = LogInfo.UNKNOWN_OPERATE;
        if (Objects.nonNull(method) && method.isAnnotationPresent(ApiOperation.class)) {
            operate = method.getAnnotation(ApiOperation.class).value();
        }
        return operate;
    }

    /**
     * 根据controller上的方法@OperateInfo注解的内容，返回当前[业务类型]以及[严重度]
     */
    public static LogEnum getOperateInfoByMethod(Method method) {
        LogEnum logEnum = LogEnum.BUSINESS_COMMON;
        if(Objects.nonNull(method) && method.isAnnotationPresent(OperateInfo.class)){
            logEnum = method.getAnnotation(OperateInfo.class).info();
        }
        return logEnum;
    }

    /**
     * 根据controller上的方法@OperateInfo注解的内容，返回当前操作类型
     */
    public static String getOperateTypeByMethod(Method method) {
        String operateType = OperateType.QUERY;
        if(Objects.nonNull(method) && method.isAnnotationPresent(OperateInfo.class)){
            operateType = method.getAnnotation(OperateInfo.class).operateType();
        }
        return operateType;
    }

}
