package com.fuyuanshen.common.ratelimiter.aspectj;// DeviceRedisKeyAspect.java

import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONUtil;
import com.fuyuanshen.common.core.exception.ServiceException;
import com.fuyuanshen.common.core.utils.StringUtils;
import com.fuyuanshen.common.ratelimiter.annotation.FunctionAccessBatcAnnotation;
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 java.util.List;

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

@Slf4j
@Aspect
@Component
public class FunctionAccessBatchAspect {

    // 定义切点，拦截带有DeviceRedisKeyAnnotation注解的方法
    @Around("@annotation(functionAccessBatchAspect)")
    public Object addDeviceRedisKey(ProceedingJoinPoint joinPoint, FunctionAccessBatcAnnotation functionAccessBatchAspect) throws Throwable {
        Object result;
        String batchId = null;
        List<String> deviceImeiList = null;

        // 获取方法参数，查找设备ID
        Object[] args = joinPoint.getArgs();
        batchId = extractDeviceBatchId(args);
        deviceImeiList = extractDeviceImeiList(args);
        if (StringUtils.isNotBlank(batchId)) {
            // 生成全局Redis key
            String redisKey = generateDeviceRedisKey(batchId);
            String cacheKey = RedisUtils.getCacheObject(redisKey);
            if(StringUtils.isNotBlank(cacheKey) && "ACTIVE".equals(cacheKey)){
                throw new ServiceException("设备已存在访问限制，请稍后再试", 500);
            }
            deviceImeiList.forEach(item->{
                RedisUtils.setCacheObject(FUNCTION_ACCESS_KEY + item, "ACTIVE", Duration.ofSeconds(functionAccessBatchAspect.timeOut()));
            });
            String deviceImeiListStr = JSONUtil.toJsonStr(deviceImeiList);
            RedisUtils.setCacheObject(redisKey, deviceImeiListStr , Duration.ofSeconds(functionAccessBatchAspect.batchMaxTimeOut()));
        }
        
        // 执行原方法
        result = joinPoint.proceed();
        
        return result;
    }

    /**
     * 从方法参数中提取设备IMEI列表
     */
    private List<String> extractDeviceImeiList(Object[] args) {
        if (args == null || args.length == 0) {
            return null;
        }

        for (Object arg : args) {
            if (arg == null) continue;

            // 如果参数本身就是List<String>类型
            if (arg instanceof List) {
                List<?> list = (List<?>) arg;
                if (!list.isEmpty() && list.get(0) instanceof String) {
                    // 检查是否为deviceImeiList
                    return (List<String>) list;
                }
            }

            // 如果参数是对象，尝试获取deviceImeiList字段
            try {
                // 使用反射获取deviceImeiList字段
                java.lang.reflect.Field[] fields = arg.getClass().getDeclaredFields();
                for (java.lang.reflect.Field field : fields) {
                    if ("deviceImeiList".equalsIgnoreCase(field.getName()) ||
                            "device_imei_list".equalsIgnoreCase(field.getName()) ||
                            "deviceImeis".equalsIgnoreCase(field.getName()) ||
                            "device_imeis".equalsIgnoreCase(field.getName())) {
                        field.setAccessible(true);
                        Object value = field.get(arg);
                        if (value instanceof List) {
                            List<?> list = (List<?>) value;
                            if (!list.isEmpty() && list.get(0) instanceof String) {
                                return (List<String>) list;
                            }
                        }
                    }
                }

                // 尝试获取getDeviceImeiList方法
                try {
                    java.lang.reflect.Method getDeviceImeiListMethod = arg.getClass().getMethod("getDeviceImeiList");
                    Object value = getDeviceImeiListMethod.invoke(arg);
                    if (value instanceof List) {
                        List<?> list = (List<?>) value;
                        if (!list.isEmpty() && list.get(0) instanceof String) {
                            return (List<String>) list;
                        }
                    }
                } catch (Exception ignored) {}

                // 尝试获取getDeviceImeis方法
                try {
                    java.lang.reflect.Method getDeviceImeisMethod = arg.getClass().getMethod("getDeviceImeis");
                    Object value = getDeviceImeisMethod.invoke(arg);
                    if (value instanceof List) {
                        List<?> list = (List<?>) value;
                        if (!list.isEmpty() && list.get(0) instanceof String) {
                            return (List<String>) list;
                        }
                    }
                } catch (Exception ignored) {}

            } catch (Exception e) {
                log.debug("从参数中提取设备IMEI列表时出错: {}", e.getMessage());
            }
        }

        return null;
    }


    /**
     * 从方法参数中提取设备ID
     */
    private String extractDeviceBatchId(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 ("batchId".equalsIgnoreCase(field.getName()) ||
                        "batch_id".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("batchId");
                    Object value = getIdMethod.invoke(arg);
                    if (value != null) {
                        return value.toString();
                    }
                } catch (Exception ignored) {}
                
            } catch (Exception e) {
                log.debug("从参数中提取批次号时出错: {}", e.getMessage());
            }
        }
        
        return null;
    }
    
    /**
     * 生成设备的全局Redis key
     */
    private String generateDeviceRedisKey(String batchId) {
        return FUNCTION_ACCESS_KEY + batchId;
    }
}
