package com.kexue.skills.aspect;

import com.kexue.skills.annotation.RequireAuth;
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 jakarta.annotation.Resource;
/**
 * @author 维哥
 * @Description 登录认证切面
 * @create 2025-02-25 15:43
 */
@Aspect
@Component
@Slf4j
public class AuthAspect {

    @Resource
    private SysUserService sysUserService;
    
    // 处理方法级别注解
    @Around("@annotation(com.kexue.skills.annotation.RequireAuth)")
    public Object requireAuthMethod(ProceedingJoinPoint joinPoint) throws Throwable {
        return requireAuthImpl(joinPoint);
    }
    
    // 处理类级别注解
    @Around("@within(com.kexue.skills.annotation.RequireAuth)")
    public Object requireAuthClass(ProceedingJoinPoint joinPoint) throws Throwable {
        return requireAuthImpl(joinPoint);
    }
    
    // 实际的认证逻辑
    private Object requireAuthImpl(ProceedingJoinPoint joinPoint) throws Throwable {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        String token = request.getHeader("Authorization");
        StringBuffer requestURL = request.getRequestURL();
        
        // 获取方法签名
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        
        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(), 
                     signature.getDeclaringType().getSimpleName(), 
                     signature.getMethod().getName());
            
            // 设置用户上下文
            UserContextHolder.setUserName(username);
        } catch (Exception e) {
            log.error("认证失败：{}", e.getMessage());
            throw new BizException(ResultCode.TOKEN_FAILED.getCode(), "无效的token，请重新登录");
        }
        return joinPoint.proceed();
    }
}