package cn.iocoder.foodnexus.module.system.aspect;

import cn.iocoder.foodnexus.framework.security.core.util.SecurityFrameworkUtils;
import cn.iocoder.foodnexus.module.system.annotations.AppSystemAuth;
import cn.iocoder.foodnexus.module.system.dal.dataobject.user.AdminUserDO;
import cn.iocoder.foodnexus.framework.common.enums.UserSystemEnum;
import cn.iocoder.foodnexus.module.system.service.user.AdminUserService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.*;

import static cn.iocoder.foodnexus.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.foodnexus.module.system.enums.ErrorCodeConstants.NOT_APP_USER;
import static cn.iocoder.foodnexus.module.system.enums.ErrorCodeConstants.USER_SYSTEM_ERROR;

/**
 * @author : yanghao
 * create at:  2025/4/24  17:27
 * @description: app用户鉴别
 */
@Slf4j
@Aspect
@Component
@RequiredArgsConstructor
public class AppSystemAspect {

    private final AdminUserService userService;

    public static Map<Long, String> CACHE = new HashMap<>();

    // 前置通知：在目标方法执行前执行
    @Before("@within(cn.iocoder.foodnexus.module.system.annotations.AppSystemAuth) || @annotation(cn.iocoder.foodnexus.module.system.annotations.AppSystemAuth)")
    public void beforeAppSystemAuth(JoinPoint joinPoint) {
        Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();
        Class<?> targetClass = joinPoint.getTarget().getClass();

        // 1️⃣ 优先取方法上的注解
        AppSystemAuth appSystemAuth = method.getAnnotation(AppSystemAuth.class);

        // 2️⃣ 如果方法上没有，再取类上的注解
        if (appSystemAuth == null) {
            appSystemAuth = targetClass.getAnnotation(AppSystemAuth.class);
        }

        Long loginUserId = SecurityFrameworkUtils.getLoginUserId();
        String userSystem;
        if (CACHE.containsKey(loginUserId)) {
            userSystem = CACHE.get(loginUserId);
        } else {
            AdminUserDO user = userService.getUser(loginUserId);
            userSystem = user.getUserSystem();
            CACHE.put(loginUserId, userSystem);
        }

        // 校验用户体系是否在允许范围内
        if (Arrays.stream(appSystemAuth.value()).noneMatch(e -> Objects.equals(e.getKey(), userSystem))) {
            throw exception(USER_SYSTEM_ERROR, Arrays.stream(appSystemAuth.value()).toList());
        }
    }

}
