package com.backendsys.modules.common.aspect;

import cn.hutool.core.convert.Convert;
import com.backendsys.modules.common.utils.Result;
import com.backendsys.modules.common.utils.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.boot.web.reactive.context.AnnotationConfigReactiveWebApplicationContext;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;

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

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

/**
 * 待弃用
 */
@Aspect
@Component
public class QueryNullCheckAspectV2 {

    @Autowired
    private ApplicationContext applicationContext;

    private static Map<String, Object> queryResult;
    private static Object queryResultV2;

    /**
     * 自定注解：@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(queryNullCheckV2)")
    public Object handleQueryNullCheck(ProceedingJoinPoint joinPoint, QueryNullCheckV2 queryNullCheckV2) throws Throwable {
        Object[] args = joinPoint.getArgs();

        Object service = applicationContext.getBean(queryNullCheckV2.service());

        String argField = queryNullCheckV2.field();
        String message = queryNullCheckV2.message();

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

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

            // 拿不到 selectById 方法
            // 在MyBatis-Plus中，BaseMapper<T>接口中定义的方法（如selectById）是通过MyBatis-Plus框架在运行时动态生成的代理实现的。这些方法并不是直接在DAO接口的实现类中定义的，而是在代理对象中动态创建的。因此，使用Java反射API直接在DAO接口的实现类中查找这些方法是找不到的。

//            System.out.println(argService);
//            System.out.println(argService.getClass());
//            System.out.println(argService.getClass().getMethods());
//            for (Method method : argService.getClass().getMethods()) {
//                System.out.println("method: " + method);
//            }

            queryResultV2 = service.getClass().getMethod("selectById", argValue.getClass()).invoke(service, argValue);
            if (queryResult == null) {
                return Result.error(ResultEnum.DATABASE_OPERATION_FAILED.getCode(), message);
            }
            System.out.println(queryResultV2);
        }

        return joinPoint.proceed();
    }

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