package com.haha.admin.aspect;

import cn.dev33.satoken.stp.StpUtil;
import com.haha.admin.annotation.RequirePermission;
import com.haha.admin.annotation.SuperAdmin;
import com.haha.common.vo.Result;
import com.haha.service.DataPermissionService;
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.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;

/**
 * 权限校验切面
 */
@Slf4j
@Aspect
@Component
public class PermissionAspect {

    @Autowired
    private DataPermissionService dataPermissionService;

    /**
     * 超级管理员角色ID
     */
    private static final Long SUPER_ADMIN_ROLE_ID = 1L;

    /**
     * 拦截带有@RequirePermission注解的方法
     */
    @Around("@annotation(com.haha.admin.annotation.RequirePermission)")
    public Object checkPermission(ProceedingJoinPoint joinPoint) throws Throwable {
        // 获取当前登录用户ID
        Object loginId = StpUtil.getLoginId();
        if (loginId == null) {
            log.warn("权限校验失败: 未登录");
            return Result.error(401, "请先登录");
        }

        // 获取方法上的注解
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        RequirePermission annotation = method.getAnnotation(RequirePermission.class);
        
        if (annotation == null) {
            return joinPoint.proceed();
        }

        String requiredPermission = annotation.value();
        log.debug("权限校验: userId={}, requiredPermission={}", loginId, requiredPermission);

        // 获取用户的角色ID列表
        String roleIdsStr = (String) StpUtil.getSession().get("roleIds");
        if (roleIdsStr == null || roleIdsStr.trim().isEmpty()) {
            log.warn("权限校验失败: 用户无角色 userId={}", loginId);
            return Result.error(403, annotation.message());
        }

        // 解析角色ID列表
        List<Long> roleIds = Arrays.stream(roleIdsStr.split(","))
                .map(String::trim)
                .filter(s -> !s.isEmpty())
                .map(Long::parseLong)
                .toList();

        // 检查是否是超级管理员
        if (roleIds.contains(SUPER_ADMIN_ROLE_ID)) {
            log.debug("超级管理员跳过权限校验: userId={}", loginId);
            return joinPoint.proceed();
        }

        // 获取用户的权限列表
        List<String> userPermissions = dataPermissionService.getPermissionCodesByRoleIds(roleIds);
        
        // 检查是否拥有所需权限
        if (userPermissions.contains(requiredPermission)) {
            log.debug("权限校验通过: userId={}, permission={}", loginId, requiredPermission);
            return joinPoint.proceed();
        }

        log.warn("权限校验失败: userId={}, requiredPermission={}, userPermissions={}", 
                loginId, requiredPermission, userPermissions);
        return Result.error(403, annotation.message());
    }

    /**
     * 拦截带有@SuperAdmin注解的方法
     */
    @Around("@annotation(com.haha.admin.annotation.SuperAdmin)")
    public Object checkSuperAdmin(ProceedingJoinPoint joinPoint) throws Throwable {
        // 获取当前登录用户ID
        Object loginId = StpUtil.getLoginId();
        if (loginId == null) {
            log.warn("超级管理员校验失败: 未登录");
            return Result.error(401, "请先登录");
        }

        // 获取方法上的注解
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        SuperAdmin annotation = method.getAnnotation(SuperAdmin.class);
        
        String message = annotation != null ? annotation.message() : "仅超级管理员可访问";

        // 获取用户的角色ID列表
        String roleIdsStr = (String) StpUtil.getSession().get("roleIds");
        if (roleIdsStr == null || roleIdsStr.trim().isEmpty()) {
            log.warn("超级管理员校验失败: 用户无角色 userId={}", loginId);
            return Result.error(403, message);
        }

        // 解析角色ID列表
        List<Long> roleIds = Arrays.stream(roleIdsStr.split(","))
                .map(String::trim)
                .filter(s -> !s.isEmpty())
                .map(Long::parseLong)
                .toList();

        // 检查是否是超级管理员
        if (roleIds.contains(SUPER_ADMIN_ROLE_ID)) {
            log.debug("超级管理员校验通过: userId={}", loginId);
            return joinPoint.proceed();
        }

        log.warn("超级管理员校验失败: userId={}", loginId);
        return Result.error(403, message);
    }
}
