package com.jy.framework.satoken;

import cn.dev33.satoken.exception.NotPermissionException;
import cn.dev33.satoken.interceptor.SaInterceptor;
import cn.dev33.satoken.stp.StpUtil;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.jy.framework.model.constants.SaSessionKey;
import com.jy.framework.utils.ServletUtil;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.NonNull;
import org.springframework.stereotype.Component;

import java.util.Map;

@Component
public class JySaInterceptor extends SaInterceptor {

    @Resource
    private PathPermission pathPermission;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        // saToken权限验证
        boolean b = super.preHandle(request, response, handler);

        // saToken权限验证不通过
        if (!b) {
            return false;
        }

        // 验证是否登录
        StpUtil.checkLogin();

        // 获取当前登录用户信息
        UserInfo userInfo = (UserInfo) StpUtil.getTokenSession().get(SaSessionKey.USER_INFO);

        // 创建登录上下文
        LoginContext.create(userInfo);

        // 如果是超级管理员，则不进行权限校验
        if (LoginContext.isSupperAdmin()) {
            return true;
        }

        // 获取当前请求方法
        String method = request.getMethod();

        // 获取匹配路径
        String bestMatching = ServletUtil.getBestMatching(request);

        // 获取需要权限认证的接口和接口对应的权限码
        Map<String, String> map = pathPermission.get();

        // 如果当前请求接口未匹配到权限标识，则不进行权限校验
        String code = map.get(method + StringPool.SPACE + bestMatching);
        if (code == null) {
            return true;
        }

        // 当前用户拥有该权限，放行
        if (LoginContext.getApiPermissionSet().contains(code)) {
            return true;
        }

        // 当前用户未拥有该权限，抛出异常
        throw new NotPermissionException(code);
    }

    @Override
    public void afterCompletion(@NonNull HttpServletRequest request, @NonNull HttpServletResponse response, @NonNull Object handler, Exception ex) {
        LoginContext.remove();
    }

}
