package com.fuyuanshen.common.ratelimiter.aspectj;// DeviceRedisKeyAspect.java
import com.fuyuanshen.common.core.exception.ServiceException;
import com.fuyuanshen.common.core.utils.StringUtils;
import com.fuyuanshen.common.ratelimiter.annotation.FunctionAccessAnnotation;
import com.fuyuanshen.common.redis.utils.RedisUtils;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;

import java.time.Duration;

import static com.fuyuanshen.common.core.constant.GlobalConstants.FUNCTION_ACCESS_KEY;
import static com.fuyuanshen.common.core.constant.GlobalConstants.FUNCTION_ACCESS_TIMEOUT_KEY;

@Slf4j
@Aspect
@Component
public class FunctionAccessAspect {

    // 定义切点，拦截带有DeviceRedisKeyAnnotation注解的方法
    @Around("@annotation(functionAccessAnnotation)")
    public Object addDeviceRedisKey(ProceedingJoinPoint joinPoint, FunctionAccessAnnotation functionAccessAnnotation) throws Throwable {
        Object result;
        String deviceImei = null;

        // 获取方法参数，查找设备ID
        Object[] args = joinPoint.getArgs();
        deviceImei = extractDeviceImei(args);
        long timeout = functionAccessAnnotation.timeOut();

        if (StringUtils.isNotBlank(deviceImei)) {
            // 生成全局Redis key
            String redisKey = generateDeviceRedisKey(deviceImei);
            String cacheKey = RedisUtils.getCacheObject(redisKey);
            if(StringUtils.isNotBlank(cacheKey) && "ACTIVE".equals(cacheKey)){
                throw new ServiceException("设备已存在访问限制，请稍后再试", 500);
            }
            //
            RedisUtils.setCacheObject(redisKey, "ACTIVE", Duration.ofSeconds(timeout));
        }
        
        // 执行原方法
        result = joinPoint.proceed();
        
        return result;
    }
    
    /**
     * 从方法参数中提取设备ID
     */
    private String extractDeviceImei(Object[] args) {
        if (args == null || args.length == 0) {
            return null;
        }
        
        for (Object arg : args) {
            if (arg == null) continue;
            
            // 如果参数本身就是设备ID (Long类型)
            if (arg instanceof Long) {
                return arg.toString();
            }
            
            // 如果参数是对象，尝试获取deviceId字段
            try {
                // 使用反射获取deviceId字段
                java.lang.reflect.Field[] fields = arg.getClass().getDeclaredFields();
                for (java.lang.reflect.Field field : fields) {
                    if ("deviceImei".equalsIgnoreCase(field.getName()) ||
                        "device_imei".equalsIgnoreCase(field.getName())) {
                        field.setAccessible(true);
                        Object value = field.get(arg);
                        if (value != null) {
                            return value.toString();
                        }
                    }
                }
                
                // 尝试获取getId方法
                try {
                    java.lang.reflect.Method getIdMethod = arg.getClass().getMethod("getDeviceImei");
                    Object value = getIdMethod.invoke(arg);
                    if (value != null) {
                        return value.toString();
                    }
                } catch (Exception ignored) {}
                
            } catch (Exception e) {
                log.debug("从参数中提取设备ID时出错: {}", e.getMessage());
            }
        }
        
        return null;
    }
    
    /**
     * 生成设备的全局Redis key
     */
    private String generateDeviceRedisKey(String deviceImei) {
        return FUNCTION_ACCESS_KEY + deviceImei;
    }
}
