package com.backendsys.aspect;

import com.backendsys.utils.response.Result;
import com.backendsys.utils.response.ResultEnum;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Map;

/**
 * 仅判断非空，可以使用此切面方法
 * 
 * 多判断，不适合此方法，比如：
 * - 非空
 * - 非本人
 * - 非超级管理员
 */

@Aspect
@Component
public class QueryNullCheckAspect {

    @Autowired
    private ApplicationContext applicationContext;

    private static Map<String, Object> queryResult;

    /**
     * 自定注解：@QueryNullCheck
     * 使用方法：通过ID查询记录是否存在 (适用于 详情/改/删)
     * @QueryNullCheck(serviceClass = B2cGoodUnitService.class, serviceMethod = "queryGoodUnitDetail", argField = "good_unit_id", message = "商品单位不存在")
     * public Result deleteGoodUnit(@Validated(B2cGoodUnitDTO.Delete.class) @RequestBody B2cGoodUnitDTO b2cGoodUnitDTO) {
     *
     * 注意：入参必须是实体类 (除 GET 外，POST/PUT/DELETE 需要加 @RequestBody)
     */
    @SuppressWarnings({"rawtypes", "unchecked"})
    @Around("@annotation(queryNullCheck)")
    public Object handleQueryNullCheck(ProceedingJoinPoint joinPoint, QueryNullCheck queryNullCheck) throws Throwable {
        Object[] args = joinPoint.getArgs();

        // 从上下文中获得 service class
        Class serviceClass = queryNullCheck.serviceClass();
        Object service = applicationContext.getBean(serviceClass);

        String serviceMethod = queryNullCheck.serviceMethod();
        String argField = queryNullCheck.argField();
        String message = queryNullCheck.message();

        // 获取参数值
        Object argValue = null;
        for (Object arg : args) {
            Field field = arg.getClass().getDeclaredField(argField);
            field.setAccessible(true);
            argValue = field.get(arg);
            if (argValue != null) { break; }
        }

        /**
         * 参数为空 (例如 user_id = null) 时，校验在实体类那里进行，此处不再进行校验
         */
        if (argValue != null) {

            System.out.println("---");
            for(Method method : service.getClass().getMethods()) {
                System.out.println("method = " + method);
            }
            System.out.println("---");

            System.out.println("service.getClass() = " + service.getClass());
            System.out.println("serviceMethod = " + serviceMethod);
            System.out.println("argValue.getClass() = " + argValue.getClass());

            // [反向代理] 执行记录非空查询的 service 方法
            queryResult = (Map<String, Object>) service.getClass().getMethod(serviceMethod, argValue.getClass()).invoke(service, argValue);
            // System.out.println("queryResult = " + queryResult);
            if (queryResult == null) {
                return Result.error(ResultEnum.DATABASE_OPERATION_FAILED.getCode(), message);
            }
        }

        return joinPoint.proceed();
    }

    /**
     * 获得该次查询的结果：
     * QueryNullCheckAspect.getQueryResult()
     */
    public static Map<String, Object> getQueryResult() {
        return queryResult;
    }
}
