package com.kexue.skills.aspect;

import com.kexue.skills.annotation.RequireRole;
import com.kexue.skills.common.ResultCode;
import com.kexue.skills.exception.BizException;
import com.kexue.skills.interceptor.UserContextHolder;
import com.kexue.skills.service.SysUserService;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import jakarta.servlet.http.HttpServletRequest;
import javax.annotation.Resource;
import java.util.List;

/**
 * @author 维哥
 * @Description 角色权限验证切面
 * @create 2025-02-25 15:43
 */
@Aspect
@Component
@Slf4j
public class RoleAspect {

    @Resource
    private SysUserService sysUserService;

    // 处理方法级别注解
    @Around("@annotation(com.kexue.skills.annotation.RequireRole)")
    public Object requireRoleMethod(ProceedingJoinPoint joinPoint) throws Throwable {
        return requireRoleImpl(joinPoint);
    }
    
    // 处理类级别注解
    @Around("@within(com.kexue.skills.annotation.RequireRole)")
    public Object requireRoleClass(ProceedingJoinPoint joinPoint) throws Throwable {
        return requireRoleImpl(joinPoint);
    }
    
    // 实际的权限验证逻辑
    private Object requireRoleImpl(ProceedingJoinPoint joinPoint) throws Throwable {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        String token = request.getHeader("Authorization");
        StringBuffer requestURL = request.getRequestURL();
        
        // 从joinPoint获取方法签名和注解
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        
        // 先从方法上获取注解
        RequireRole requireRole = signature.getMethod().getAnnotation(RequireRole.class);
        
        // 如果方法上没有，再从类上获取
        if (requireRole == null) {
            requireRole = (RequireRole)signature.getDeclaringType().getAnnotation(RequireRole.class);
        }
        
        // 确保注解存在
        if (requireRole == null) {
            log.error("无法获取RequireRole注解，方法：{}，类：{}", 
                      signature.getMethod().getName(), 
                      signature.getDeclaringType().getName());
            throw new BizException(ResultCode.PERMISSION_DENIED.getCode(), "无法验证权限，缺少注解配置");
        }
        
        try {
            // 使用Sa-Token检查登录状态
            cn.dev33.satoken.stp.StpUtil.checkLogin();
            
            // 获取当前登录用户ID
            Object loginId = cn.dev33.satoken.stp.StpUtil.getLoginId();
            
            // 根据用户ID获取用户名
            String username = sysUserService.queryById(Long.parseLong(loginId.toString())).getUserName();
            
            log.info("用户名：{}，token：{}, URL:{}, 需要角色：{}", username, token, requestURL.toString(), String.join(",", requireRole.value()));
            log.debug("获取到的RequireRole注解：value={}, 注解类型：{}", 
                      String.join(",", requireRole.value()), 
                      requireRole.getClass().getName());
            
            // 获取用户的角色列表
            String[] requiredRoles = requireRole.value();
            if (requiredRoles != null && requiredRoles.length > 0) {
                // 获取当前用户的角色列表
                List<String> userRoles = cn.dev33.satoken.stp.StpUtil.getRoleList();
                log.info("当前用户的角色列表：{}", String.join(",", userRoles));
                
                // 检查用户是否拥有所有必需的角色
                boolean hasAllRoles = true;
                for (String role : requiredRoles) {
                    if (!userRoles.contains(role)) {
                        hasAllRoles = false;
                        log.error("用户缺少角色：{}", role);
                        break;
                    }
                }
                
                if (!hasAllRoles) {
                    throw new cn.dev33.satoken.exception.NotRoleException(requiredRoles[0]);
                }
            }
            
            // 设置用户上下文
            UserContextHolder.setUserName(username);
            

        } catch (cn.dev33.satoken.exception.NotLoginException e) {
            log.error("未登录：{}", e.getMessage());
            throw new BizException(ResultCode.TOKEN_FAILED.getCode(), "请先登录认证后操作");
        } catch (cn.dev33.satoken.exception.NotRoleException e) {
            log.error("权限不足：{}", e.getMessage());
            throw new BizException(ResultCode.PERMISSION_DENIED.getCode(), "没有访问权限");
        } catch (Exception e) {
            log.error("权限验证失败：{}", e.getMessage());
            throw new BizException(ResultCode.PERMISSION_DENIED.getCode(), "权限验证失败");
        }
        return joinPoint.proceed();
    }
}