package com.greenorange.promotion.aop;

import com.auth0.jwt.interfaces.DecodedJWT;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.greenorange.promotion.annotation.RequiresPermission;
import com.greenorange.promotion.common.ErrorCode;
import com.greenorange.promotion.exception.BusinessException;
import com.greenorange.promotion.exception.ThrowUtils;
import com.greenorange.promotion.model.entity.UserInfo;
import com.greenorange.promotion.model.enums.UserRoleEnum;
import com.greenorange.promotion.service.userInfo.UserInfoService;
import com.greenorange.promotion.utils.JWTUtils;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import java.util.HashMap;
import java.util.Map;
import java.util.Objects;


/**
 * 权限校验AOP
 */

@Slf4j
@Aspect
@Component
public class PermissionCheck {


    @Resource
    private UserInfoService userInfoService;


    @Resource
    private JWTUtils jwtUtils;

 
    /***
     * 执行拦截
     **/
    @Around("@annotation(requiresPermission)")
    public Object check(ProceedingJoinPoint joinPoint, RequiresPermission requiresPermission) throws Throwable {
        // 获取请求对象
        HttpServletRequest request = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
        // 接口的权限
        String mustRole = requiresPermission.mustRole();
        // 获取接口权限的枚举类
        UserRoleEnum interfaceRoleEnum = UserRoleEnum.getEnumByValue(mustRole);
        ThrowUtils.throwIf(interfaceRoleEnum == null, ErrorCode.NO_AUTH_ERROR);
        // 获取用户权限
        String token = request.getHeader("Authorization");
        ThrowUtils.throwIf(StringUtils.isBlank(token), ErrorCode.NO_AUTH_ERROR, "token为空");
        // 解析token
        DecodedJWT decodedJWT;
        try {
            decodedJWT = jwtUtils.verify(token);
        } catch (Exception e) {
            throw new BusinessException(ErrorCode.NO_AUTH_ERROR, "token已过期");
        }
        String userAccount = decodedJWT.getClaim("userAccount").asString();
        String userPassword = decodedJWT.getClaim("userPassword").asString();
        String userRole = decodedJWT.getClaim("userRole").asString();
        // 查询用户信息
        LambdaQueryWrapper<UserInfo> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(UserInfo::getUserAccount, userAccount).eq(UserInfo::getUserPassword, userPassword);
        // 如果是小程序用户, 就加上权限条件
        lambdaQueryWrapper.eq(StringUtils.isNotBlank(userRole), UserInfo::getUserRole, userRole);
        UserInfo userInfo = userInfoService.getOne(lambdaQueryWrapper);
        ThrowUtils.throwIf(userInfo == null, ErrorCode.OPERATION_ERROR, "用户不存在");
        // 将用户id存入request，方便后续在接口中使用
        request.setAttribute("userId", userInfo.getId());

        // 获取用户权限的枚举类
        if (userRole == null) userRole = userInfo.getUserRole();
        UserRoleEnum userRoleEnum = UserRoleEnum.getEnumByValue(userRole);

        // 校验角色
        ThrowUtils.throwIf(UserRoleEnum.BAN.equals(userRoleEnum), ErrorCode.PARAMS_ERROR, "用户已被封禁");
        Map<UserRoleEnum, Integer> userRoleMap = new HashMap<>();
        userRoleMap.put(UserRoleEnum.USER, 1);
        userRoleMap.put(UserRoleEnum.STAFF, 2);
        userRoleMap.put(UserRoleEnum.SUPERVISOR, 3);
        userRoleMap.put(UserRoleEnum.MANAGER, 4);
        userRoleMap.put(UserRoleEnum.ADMIN, 5);
        userRoleMap.put(UserRoleEnum.BOSS, 6);

        Integer userRoleNumber = userRoleMap.get(userRoleEnum);
        Integer interfaceRoleNumber = userRoleMap.get(interfaceRoleEnum);
        if (userRoleNumber == 1) {
            ThrowUtils.throwIf(interfaceRoleNumber > 1, ErrorCode.NO_AUTH_ERROR);
        } else if (userRoleNumber == 2) {
            ThrowUtils.throwIf(interfaceRoleNumber > 2, ErrorCode.NO_AUTH_ERROR);
        } else if (userRoleNumber == 3) {
            ThrowUtils.throwIf(interfaceRoleNumber > 3, ErrorCode.NO_AUTH_ERROR);
        } else if (userRoleNumber == 4) {
            ThrowUtils.throwIf(interfaceRoleNumber > 4, ErrorCode.NO_AUTH_ERROR);
        } else if (userRoleNumber == 5) {
            ThrowUtils.throwIf(interfaceRoleNumber != 5, ErrorCode.NO_AUTH_ERROR);
        } else {
            ThrowUtils.throwIf(interfaceRoleNumber < 5, ErrorCode.NO_AUTH_ERROR);
        }

        return joinPoint.proceed();
    }
 
}